opencode-swarm 7.38.0 → 7.39.0

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.38.0",
37
+ version: "7.39.0",
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",
@@ -38860,6 +38860,110 @@ var init_close = __esm(() => {
38860
38860
  ];
38861
38861
  });
38862
38862
 
38863
+ // src/commands/concurrency.ts
38864
+ async function handleConcurrencyCommand(directory, args, sessionID) {
38865
+ if (!sessionID || sessionID.trim() === "") {
38866
+ return "Error: No active session context. Concurrency requires an active session. Use /swarm concurrency from within an OpenCode session, or start a session first.";
38867
+ }
38868
+ const session = getAgentSession(sessionID);
38869
+ if (!session) {
38870
+ return "Error: No active session. Concurrency requires an active session to operate.";
38871
+ }
38872
+ const arg0 = args[0]?.toLowerCase();
38873
+ const arg1 = args[1];
38874
+ const plan = await loadPlanJsonOnly(directory).catch(() => null);
38875
+ const hasPlan = plan !== null && plan !== undefined;
38876
+ if (arg0 === undefined) {
38877
+ return [
38878
+ "Concurrency commands:",
38879
+ " /swarm concurrency set <N|preset> \u2014 Set session concurrency override (1-64 or min/medium/max)",
38880
+ " /swarm concurrency status \u2014 Show effective concurrency",
38881
+ " /swarm concurrency reset \u2014 Clear the override"
38882
+ ].join(`
38883
+ `);
38884
+ }
38885
+ if (arg0 === "status") {
38886
+ return buildStatusMessage(session, plan);
38887
+ }
38888
+ if (!hasPlan) {
38889
+ if (arg0 === "set") {
38890
+ return "No active plan. Concurrency override requires an active plan.";
38891
+ }
38892
+ }
38893
+ if (arg0 === "reset") {
38894
+ session.maxConcurrencyOverride = undefined;
38895
+ return "Concurrency override cleared";
38896
+ }
38897
+ if (arg0 === "set") {
38898
+ if (arg1 === undefined) {
38899
+ return "Error: /swarm concurrency set requires a value. Usage: /swarm concurrency set <N|preset>";
38900
+ }
38901
+ return handleSetCommand(session, arg1);
38902
+ }
38903
+ return [
38904
+ `Unknown concurrency subcommand: ${arg0}`,
38905
+ "Usage: /swarm concurrency <set|status|reset>"
38906
+ ].join(`
38907
+ `);
38908
+ }
38909
+ function handleSetCommand(session, value) {
38910
+ const normalizedValue = value.toLowerCase();
38911
+ if (normalizedValue in PRESETS) {
38912
+ const presetConcurrency = PRESETS[normalizedValue];
38913
+ session.maxConcurrencyOverride = presetConcurrency;
38914
+ return `Concurrency override set to ${presetConcurrency} (${normalizedValue})`;
38915
+ }
38916
+ const numericValue = Number(value);
38917
+ if (Number.isNaN(numericValue)) {
38918
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
38919
+ }
38920
+ if (!Number.isInteger(numericValue)) {
38921
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
38922
+ }
38923
+ if (numericValue < MIN_CONCURRENCY || numericValue > MAX_CONCURRENCY) {
38924
+ return `Concurrency value ${value} is out of range. Must be between ${MIN_CONCURRENCY} and ${MAX_CONCURRENCY}.`;
38925
+ }
38926
+ session.maxConcurrencyOverride = numericValue;
38927
+ return `Concurrency override set to ${numericValue}`;
38928
+ }
38929
+ function buildStatusMessage(session, plan) {
38930
+ const overrideActive = session.maxConcurrencyOverride !== undefined;
38931
+ const configuredOverride = session.maxConcurrencyOverride ?? "absent";
38932
+ const hasPlan = plan !== null && plan !== undefined;
38933
+ const planBaseline = hasPlan ? plan.execution_profile?.max_concurrent_tasks ?? 1 : 1;
38934
+ const parallelizationEnabled = hasPlan ? plan.execution_profile?.parallelization_enabled ?? false : false;
38935
+ const operationalEffective = !parallelizationEnabled ? 1 : session.maxConcurrencyOverride ?? planBaseline;
38936
+ let description;
38937
+ if (!hasPlan) {
38938
+ description = "No active plan";
38939
+ } else if (!parallelizationEnabled) {
38940
+ description = "Parallelization disabled (always 1)";
38941
+ } else if (overrideActive) {
38942
+ description = `Override active (${session.maxConcurrencyOverride})`;
38943
+ } else {
38944
+ description = `Plan baseline (${planBaseline})`;
38945
+ }
38946
+ return [
38947
+ `Concurrency: ${description}`,
38948
+ ` override_active: ${overrideActive}`,
38949
+ ` configured_override: ${configuredOverride}`,
38950
+ ` plan_baseline: ${planBaseline}`,
38951
+ ` operational_effective: ${operationalEffective}`,
38952
+ ` parallelization_enabled: ${parallelizationEnabled}`
38953
+ ].join(`
38954
+ `);
38955
+ }
38956
+ var PRESETS, MIN_CONCURRENCY = 1, MAX_CONCURRENCY = 64;
38957
+ var init_concurrency = __esm(() => {
38958
+ init_manager();
38959
+ init_state();
38960
+ PRESETS = {
38961
+ min: 1,
38962
+ medium: 3,
38963
+ max: 8
38964
+ };
38965
+ });
38966
+
38863
38967
  // src/commands/config.ts
38864
38968
  import * as os4 from "os";
38865
38969
  import * as path17 from "path";
@@ -44428,7 +44532,10 @@ function serializeAgentSession(s) {
44428
44532
  fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
44429
44533
  fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
44430
44534
  sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
44431
- ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
44535
+ ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion },
44536
+ ...s.maxConcurrencyOverride !== undefined && {
44537
+ maxConcurrencyOverride: s.maxConcurrencyOverride
44538
+ }
44432
44539
  };
44433
44540
  }
44434
44541
  async function writeSnapshot(directory, state) {
@@ -55699,7 +55806,7 @@ async function handleTurboCommand(directory, args, sessionID) {
55699
55806
  const arg0 = args[0]?.toLowerCase();
55700
55807
  const arg1 = args[1]?.toLowerCase();
55701
55808
  if (arg0 === "status") {
55702
- return buildStatusMessage(session, directory, sessionID);
55809
+ return buildStatusMessage2(session, directory, sessionID);
55703
55810
  }
55704
55811
  const isTurboOn = session.turboMode;
55705
55812
  const isLeanActive = session.leanTurboActive === true;
@@ -55830,7 +55937,7 @@ function enableLeanTurbo(session, directory, sessionID) {
55830
55937
  `Full-Auto: ${fullAutoActive ? "active" : "inactive"})`
55831
55938
  ].join(" ");
55832
55939
  }
55833
- function buildStatusMessage(session, directory, sessionID) {
55940
+ function buildStatusMessage2(session, directory, sessionID) {
55834
55941
  if (!session.turboMode) {
55835
55942
  return "Turbo: off";
55836
55943
  }
@@ -56278,7 +56385,6 @@ __export(exports_commands, {
56278
56385
  handleMemoryMigrateCommand: () => handleMemoryMigrateCommand,
56279
56386
  handleMemoryImportCommand: () => handleMemoryImportCommand,
56280
56387
  handleMemoryExportCommand: () => handleMemoryExportCommand,
56281
- handleMemoryEvaluateCommand: () => handleMemoryEvaluateCommand,
56282
56388
  handleMemoryCommand: () => handleMemoryCommand,
56283
56389
  handleKnowledgeRestoreCommand: () => handleKnowledgeRestoreCommand,
56284
56390
  handleKnowledgeQuarantineCommand: () => handleKnowledgeQuarantineCommand,
@@ -56298,6 +56404,7 @@ __export(exports_commands, {
56298
56404
  handleCurateCommand: () => handleCurateCommand,
56299
56405
  handleCouncilCommand: () => handleCouncilCommand,
56300
56406
  handleConfigCommand: () => handleConfigCommand,
56407
+ handleConcurrencyCommand: () => handleConcurrencyCommand,
56301
56408
  handleCloseCommand: () => handleCloseCommand,
56302
56409
  handleClarifyCommand: () => handleClarifyCommand,
56303
56410
  handleCheckpointCommand: () => handleCheckpointCommand,
@@ -56544,6 +56651,7 @@ var init_commands = __esm(() => {
56544
56651
  init_close();
56545
56652
  init_command_dispatch();
56546
56653
  init_command_names();
56654
+ init_concurrency();
56547
56655
  init_config2();
56548
56656
  init_council();
56549
56657
  init_curate();
@@ -56764,6 +56872,7 @@ var init_registry = __esm(() => {
56764
56872
  init_benchmark();
56765
56873
  init_checkpoint2();
56766
56874
  init_close();
56875
+ init_concurrency();
56767
56876
  init_config2();
56768
56877
  init_council();
56769
56878
  init_curate();
@@ -57008,6 +57117,23 @@ var init_registry = __esm(() => {
57008
57117
  aliasOf: "finalize",
57009
57118
  deprecated: true
57010
57119
  },
57120
+ concurrency: {
57121
+ handler: (ctx) => handleConcurrencyCommand(ctx.directory, ctx.args, ctx.sessionID),
57122
+ description: "Manage runtime concurrency override for plan execution [set|status|reset]",
57123
+ args: "set <N|preset>, status, reset",
57124
+ details: `Sets, queries, or clears a session-scoped concurrency override for max_concurrent_tasks during plan execution.
57125
+ When set, the override takes precedence over the plan's locked execution_profile.max_concurrent_tasks.
57126
+ ` + `The override is session-scoped \u2014 it does not modify the plan and is cleared on session reset.
57127
+ ` + `
57128
+ Subcommands:
57129
+ ` + ` concurrency set <N> \u2014 Set session concurrency to N (1-64)
57130
+ ` + ` concurrency set <preset> \u2014 Set to preset: min (1), medium (3), max (8)
57131
+ ` + ` concurrency status \u2014 Show effective concurrency (override, plan baseline, operational effective)
57132
+ ` + ` concurrency reset \u2014 Clear the session concurrency override
57133
+ ` + `
57134
+ ` + "Session-scoped \u2014 resets on new session.",
57135
+ category: "utility"
57136
+ },
57011
57137
  simulate: {
57012
57138
  handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
57013
57139
  description: "Dry-run hidden coupling analysis with configurable thresholds",
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Handles the /swarm concurrency command.
3
+ * Supports setting, resetting, and checking concurrency override values.
4
+ *
5
+ * @param directory - Project directory (used to load plan execution_profile)
6
+ * @param args - Optional arguments: "set" | "status" | "reset" with optional value
7
+ * @param sessionID - Session ID for accessing active session state
8
+ * @returns Feedback message about concurrency state
9
+ */
10
+ export declare function handleConcurrencyCommand(directory: string, args: string[], sessionID: string): Promise<string>;
@@ -11,6 +11,7 @@ export { handleCloseCommand } from './close';
11
11
  export { executeSwarmCommand, formatCommandNotFound, normalizeSwarmCommandInput, } from './command-dispatch.js';
12
12
  export type { CommandName } from './command-names.js';
13
13
  export { COMMAND_NAME_SET, COMMAND_NAMES } from './command-names.js';
14
+ export { handleConcurrencyCommand } from './concurrency';
14
15
  export { handleConfigCommand } from './config';
15
16
  export { handleCouncilCommand } from './council';
16
17
  export { handleCurateCommand } from './curate';
@@ -24,7 +25,7 @@ export { handleFullAutoCommand } from './full-auto';
24
25
  export { handleHandoffCommand } from './handoff';
25
26
  export { handleHistoryCommand } from './history';
26
27
  export { handleKnowledgeListCommand, handleKnowledgeMigrateCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, } from './knowledge';
27
- export { handleMemoryCommand, handleMemoryEvaluateCommand, handleMemoryExportCommand, handleMemoryImportCommand, handleMemoryMigrateCommand, handleMemoryStatusCommand, } from './memory';
28
+ export { handleMemoryCommand, handleMemoryExportCommand, handleMemoryImportCommand, handleMemoryMigrateCommand, handleMemoryStatusCommand, } from './memory';
28
29
  export { handlePlanCommand } from './plan';
29
30
  export { handlePreflightCommand } from './preflight';
30
31
  export { handlePromoteCommand } from './promote';
@@ -256,6 +256,13 @@ export declare const COMMAND_REGISTRY: {
256
256
  readonly aliasOf: "finalize";
257
257
  readonly deprecated: true;
258
258
  };
259
+ readonly concurrency: {
260
+ readonly handler: (ctx: CommandContext) => Promise<string>;
261
+ readonly description: "Manage runtime concurrency override for plan execution [set|status|reset]";
262
+ readonly args: "set <N|preset>, status, reset";
263
+ readonly details: string;
264
+ readonly category: "utility";
265
+ };
259
266
  readonly simulate: {
260
267
  readonly handler: (ctx: CommandContext) => Promise<string>;
261
268
  readonly description: "Dry-run hidden coupling analysis with configurable thresholds";
@@ -55,6 +55,7 @@ interface MessageWithParts {
55
55
  parts: MessagePart[];
56
56
  }
57
57
  declare function resolveDelegatedPlanTaskId(args: Record<string, unknown>, knownPlanTaskIds?: ReadonlySet<string>): string | null;
58
+ declare function buildParallelExecutionGuidance(directory: string | undefined, sessionID: string, session: AgentSessionState): Promise<string | null>;
58
59
  /**
59
60
  * Resolves the correct task ID for evidence recording by chaining:
60
61
  * 1. Explicit task_id in direct args (structured field)
@@ -68,11 +69,13 @@ declare function resolveDelegatedPlanTaskId(args: Record<string, unknown>, known
68
69
  declare function resolveEvidenceTaskId(args: Record<string, unknown> | undefined, session: AgentSessionState, directory: string): Promise<string | null>;
69
70
  /**
70
71
  * _internals export for testing — do not use in production code.
71
- * Exposes resolveEvidenceTaskId and resolveDelegatedPlanTaskId for unit testing.
72
+ * Exposes resolveEvidenceTaskId, resolveDelegatedPlanTaskId, and
73
+ * buildParallelExecutionGuidance for unit testing.
72
74
  */
73
75
  export declare const _internals: {
74
76
  resolveEvidenceTaskId: typeof resolveEvidenceTaskId;
75
77
  resolveDelegatedPlanTaskId: typeof resolveDelegatedPlanTaskId;
78
+ buildParallelExecutionGuidance: typeof buildParallelExecutionGuidance;
76
79
  };
77
80
  /**
78
81
  * Creates the experimental.chat.messages.transform hook for delegation gating.
package/dist/index.js CHANGED
@@ -48,7 +48,7 @@ var package_default;
48
48
  var init_package = __esm(() => {
49
49
  package_default = {
50
50
  name: "opencode-swarm",
51
- version: "7.38.0",
51
+ version: "7.39.0",
52
52
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
53
53
  main: "dist/index.js",
54
54
  types: "dist/index.d.ts",
@@ -40120,7 +40120,8 @@ async function buildParallelExecutionGuidance(directory, sessionID, session) {
40120
40120
  const profile = plan.execution_profile;
40121
40121
  const enabled = profile?.parallelization_enabled === true;
40122
40122
  const maxConcurrent = profile?.max_concurrent_tasks ?? 1;
40123
- if (!enabled || maxConcurrent <= 1)
40123
+ const effectiveMaxConcurrent = session?.maxConcurrencyOverride ?? maxConcurrent;
40124
+ if (!enabled || effectiveMaxConcurrent <= 1)
40124
40125
  return null;
40125
40126
  if (hasActiveLeanTurbo(sessionID)) {
40126
40127
  return "[NEXT] Lean Turbo is active; use lean_turbo_run_phase and Lean Turbo lane guidance instead of standard execution-profile slot filling.";
@@ -40149,9 +40150,9 @@ async function buildParallelExecutionGuidance(directory, sessionID, session) {
40149
40150
  if (ACTIVE_PARALLEL_TASK_STATES.has(state))
40150
40151
  occupied.add(taskId);
40151
40152
  }
40152
- const availableSlots = Math.max(0, maxConcurrent - occupied.size);
40153
+ const availableSlots = Math.max(0, effectiveMaxConcurrent - occupied.size);
40153
40154
  if (availableSlots <= 0) {
40154
- 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.`;
40155
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; all standard execution slots are occupied. Continue current active task gates before starting more coder work.`;
40155
40156
  }
40156
40157
  const eligible = tasks.filter((task) => {
40157
40158
  const taskId = task.id;
@@ -40163,9 +40164,9 @@ async function buildParallelExecutionGuidance(directory, sessionID, session) {
40163
40164
  return task.depends.every((dep) => completed.has(dep));
40164
40165
  }).map((task) => task.id).slice(0, availableSlots);
40165
40166
  if (eligible.length === 0) {
40166
- 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.`;
40167
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; no dependency-ready pending tasks are available for a new coder slot. Continue the current task/gate.`;
40167
40168
  }
40168
- 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.`;
40169
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; ${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.`;
40169
40170
  }
40170
40171
  function isParallelGuidancePhaseComplete(phase) {
40171
40172
  return phase.status === "complete" || phase.status === "completed" || phase.status === "closed";
@@ -41006,6 +41007,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
41006
41007
  turboStrategy: undefined,
41007
41008
  leanTurboActive: false,
41008
41009
  leanTurboCurrentPhase: undefined,
41010
+ maxConcurrencyOverride: undefined,
41009
41011
  qaGateSessionOverrides: {},
41010
41012
  fullAutoMode: false,
41011
41013
  fullAutoInteractionCount: 0,
@@ -60234,6 +60236,110 @@ var init_close = __esm(() => {
60234
60236
  ];
60235
60237
  });
60236
60238
 
60239
+ // src/commands/concurrency.ts
60240
+ async function handleConcurrencyCommand(directory, args2, sessionID) {
60241
+ if (!sessionID || sessionID.trim() === "") {
60242
+ return "Error: No active session context. Concurrency requires an active session. Use /swarm concurrency from within an OpenCode session, or start a session first.";
60243
+ }
60244
+ const session = getAgentSession(sessionID);
60245
+ if (!session) {
60246
+ return "Error: No active session. Concurrency requires an active session to operate.";
60247
+ }
60248
+ const arg0 = args2[0]?.toLowerCase();
60249
+ const arg1 = args2[1];
60250
+ const plan = await loadPlanJsonOnly(directory).catch(() => null);
60251
+ const hasPlan = plan !== null && plan !== undefined;
60252
+ if (arg0 === undefined) {
60253
+ return [
60254
+ "Concurrency commands:",
60255
+ " /swarm concurrency set <N|preset> — Set session concurrency override (1-64 or min/medium/max)",
60256
+ " /swarm concurrency status — Show effective concurrency",
60257
+ " /swarm concurrency reset — Clear the override"
60258
+ ].join(`
60259
+ `);
60260
+ }
60261
+ if (arg0 === "status") {
60262
+ return buildStatusMessage(session, plan);
60263
+ }
60264
+ if (!hasPlan) {
60265
+ if (arg0 === "set") {
60266
+ return "No active plan. Concurrency override requires an active plan.";
60267
+ }
60268
+ }
60269
+ if (arg0 === "reset") {
60270
+ session.maxConcurrencyOverride = undefined;
60271
+ return "Concurrency override cleared";
60272
+ }
60273
+ if (arg0 === "set") {
60274
+ if (arg1 === undefined) {
60275
+ return "Error: /swarm concurrency set requires a value. Usage: /swarm concurrency set <N|preset>";
60276
+ }
60277
+ return handleSetCommand(session, arg1);
60278
+ }
60279
+ return [
60280
+ `Unknown concurrency subcommand: ${arg0}`,
60281
+ "Usage: /swarm concurrency <set|status|reset>"
60282
+ ].join(`
60283
+ `);
60284
+ }
60285
+ function handleSetCommand(session, value) {
60286
+ const normalizedValue = value.toLowerCase();
60287
+ if (normalizedValue in PRESETS) {
60288
+ const presetConcurrency = PRESETS[normalizedValue];
60289
+ session.maxConcurrencyOverride = presetConcurrency;
60290
+ return `Concurrency override set to ${presetConcurrency} (${normalizedValue})`;
60291
+ }
60292
+ const numericValue = Number(value);
60293
+ if (Number.isNaN(numericValue)) {
60294
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
60295
+ }
60296
+ if (!Number.isInteger(numericValue)) {
60297
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
60298
+ }
60299
+ if (numericValue < MIN_CONCURRENCY || numericValue > MAX_CONCURRENCY) {
60300
+ return `Concurrency value ${value} is out of range. Must be between ${MIN_CONCURRENCY} and ${MAX_CONCURRENCY}.`;
60301
+ }
60302
+ session.maxConcurrencyOverride = numericValue;
60303
+ return `Concurrency override set to ${numericValue}`;
60304
+ }
60305
+ function buildStatusMessage(session, plan) {
60306
+ const overrideActive = session.maxConcurrencyOverride !== undefined;
60307
+ const configuredOverride = session.maxConcurrencyOverride ?? "absent";
60308
+ const hasPlan = plan !== null && plan !== undefined;
60309
+ const planBaseline = hasPlan ? plan.execution_profile?.max_concurrent_tasks ?? 1 : 1;
60310
+ const parallelizationEnabled = hasPlan ? plan.execution_profile?.parallelization_enabled ?? false : false;
60311
+ const operationalEffective = !parallelizationEnabled ? 1 : session.maxConcurrencyOverride ?? planBaseline;
60312
+ let description;
60313
+ if (!hasPlan) {
60314
+ description = "No active plan";
60315
+ } else if (!parallelizationEnabled) {
60316
+ description = "Parallelization disabled (always 1)";
60317
+ } else if (overrideActive) {
60318
+ description = `Override active (${session.maxConcurrencyOverride})`;
60319
+ } else {
60320
+ description = `Plan baseline (${planBaseline})`;
60321
+ }
60322
+ return [
60323
+ `Concurrency: ${description}`,
60324
+ ` override_active: ${overrideActive}`,
60325
+ ` configured_override: ${configuredOverride}`,
60326
+ ` plan_baseline: ${planBaseline}`,
60327
+ ` operational_effective: ${operationalEffective}`,
60328
+ ` parallelization_enabled: ${parallelizationEnabled}`
60329
+ ].join(`
60330
+ `);
60331
+ }
60332
+ var PRESETS, MIN_CONCURRENCY = 1, MAX_CONCURRENCY = 64;
60333
+ var init_concurrency = __esm(() => {
60334
+ init_manager();
60335
+ init_state();
60336
+ PRESETS = {
60337
+ min: 1,
60338
+ medium: 3,
60339
+ max: 8
60340
+ };
60341
+ });
60342
+
60237
60343
  // src/commands/config.ts
60238
60344
  import * as os7 from "node:os";
60239
60345
  import * as path28 from "node:path";
@@ -65915,7 +66021,10 @@ function serializeAgentSession(s) {
65915
66021
  fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
65916
66022
  fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
65917
66023
  sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
65918
- ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
66024
+ ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion },
66025
+ ...s.maxConcurrencyOverride !== undefined && {
66026
+ maxConcurrencyOverride: s.maxConcurrencyOverride
66027
+ }
65919
66028
  };
65920
66029
  }
65921
66030
  async function writeSnapshot(directory, state) {
@@ -78502,7 +78611,7 @@ async function handleTurboCommand(directory, args2, sessionID) {
78502
78611
  const arg0 = args2[0]?.toLowerCase();
78503
78612
  const arg1 = args2[1]?.toLowerCase();
78504
78613
  if (arg0 === "status") {
78505
- return buildStatusMessage(session, directory, sessionID);
78614
+ return buildStatusMessage2(session, directory, sessionID);
78506
78615
  }
78507
78616
  const isTurboOn = session.turboMode;
78508
78617
  const isLeanActive = session.leanTurboActive === true;
@@ -78633,7 +78742,7 @@ function enableLeanTurbo(session, directory, sessionID) {
78633
78742
  `Full-Auto: ${fullAutoActive ? "active" : "inactive"})`
78634
78743
  ].join(" ");
78635
78744
  }
78636
- function buildStatusMessage(session, directory, sessionID) {
78745
+ function buildStatusMessage2(session, directory, sessionID) {
78637
78746
  if (!session.turboMode) {
78638
78747
  return "Turbo: off";
78639
78748
  }
@@ -79081,7 +79190,6 @@ __export(exports_commands, {
79081
79190
  handleMemoryMigrateCommand: () => handleMemoryMigrateCommand,
79082
79191
  handleMemoryImportCommand: () => handleMemoryImportCommand,
79083
79192
  handleMemoryExportCommand: () => handleMemoryExportCommand,
79084
- handleMemoryEvaluateCommand: () => handleMemoryEvaluateCommand,
79085
79193
  handleMemoryCommand: () => handleMemoryCommand,
79086
79194
  handleKnowledgeRestoreCommand: () => handleKnowledgeRestoreCommand,
79087
79195
  handleKnowledgeQuarantineCommand: () => handleKnowledgeQuarantineCommand,
@@ -79101,6 +79209,7 @@ __export(exports_commands, {
79101
79209
  handleCurateCommand: () => handleCurateCommand,
79102
79210
  handleCouncilCommand: () => handleCouncilCommand,
79103
79211
  handleConfigCommand: () => handleConfigCommand,
79212
+ handleConcurrencyCommand: () => handleConcurrencyCommand,
79104
79213
  handleCloseCommand: () => handleCloseCommand,
79105
79214
  handleClarifyCommand: () => handleClarifyCommand,
79106
79215
  handleCheckpointCommand: () => handleCheckpointCommand,
@@ -79347,6 +79456,7 @@ var init_commands = __esm(() => {
79347
79456
  init_close();
79348
79457
  init_command_dispatch();
79349
79458
  init_command_names();
79459
+ init_concurrency();
79350
79460
  init_config2();
79351
79461
  init_council();
79352
79462
  init_curate();
@@ -79567,6 +79677,7 @@ var init_registry = __esm(() => {
79567
79677
  init_benchmark();
79568
79678
  init_checkpoint2();
79569
79679
  init_close();
79680
+ init_concurrency();
79570
79681
  init_config2();
79571
79682
  init_council();
79572
79683
  init_curate();
@@ -79811,6 +79922,23 @@ var init_registry = __esm(() => {
79811
79922
  aliasOf: "finalize",
79812
79923
  deprecated: true
79813
79924
  },
79925
+ concurrency: {
79926
+ handler: (ctx) => handleConcurrencyCommand(ctx.directory, ctx.args, ctx.sessionID),
79927
+ description: "Manage runtime concurrency override for plan execution [set|status|reset]",
79928
+ args: "set <N|preset>, status, reset",
79929
+ details: `Sets, queries, or clears a session-scoped concurrency override for max_concurrent_tasks during plan execution.
79930
+ When set, the override takes precedence over the plan's locked execution_profile.max_concurrent_tasks.
79931
+ ` + `The override is session-scoped — it does not modify the plan and is cleared on session reset.
79932
+ ` + `
79933
+ Subcommands:
79934
+ ` + ` concurrency set <N> — Set session concurrency to N (1-64)
79935
+ ` + ` concurrency set <preset> — Set to preset: min (1), medium (3), max (8)
79936
+ ` + ` concurrency status — Show effective concurrency (override, plan baseline, operational effective)
79937
+ ` + ` concurrency reset — Clear the session concurrency override
79938
+ ` + `
79939
+ ` + "Session-scoped — resets on new session.",
79940
+ category: "utility"
79941
+ },
79814
79942
  simulate: {
79815
79943
  handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
79816
79944
  description: "Dry-run hidden coupling analysis with configurable thresholds",
@@ -103304,6 +103432,7 @@ function deserializeAgentSession(s) {
103304
103432
  fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
103305
103433
  fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
103306
103434
  fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
103435
+ maxConcurrencyOverride: typeof s.maxConcurrencyOverride === "number" ? Math.min(64, Math.max(1, s.maxConcurrencyOverride)) : undefined,
103307
103436
  prmPatternCounts: new Map,
103308
103437
  prmEscalationLevel: 0,
103309
103438
  prmLastPatternDetected: null,
@@ -124027,7 +124156,7 @@ async function initializeOpenCodeSwarm(ctx) {
124027
124156
  ...opencodeConfig.command || {},
124028
124157
  swarm: {
124029
124158
  template: "/swarm $ARGUMENTS",
124030
- description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|memory|curate|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
124159
+ description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|memory|curate|concurrency|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
124031
124160
  },
124032
124161
  "swarm-status": {
124033
124162
  template: "/swarm status",
@@ -124157,10 +124286,6 @@ async function initializeOpenCodeSwarm(ctx) {
124157
124286
  template: "/swarm memory export",
124158
124287
  description: "Use /swarm memory export to write current memory to JSONL"
124159
124288
  },
124160
- "swarm-memory-evaluate": {
124161
- template: "/swarm memory evaluate --json",
124162
- description: "Use /swarm memory evaluate --json to generate the recall evaluation report"
124163
- },
124164
124289
  "swarm-memory-import": {
124165
124290
  template: "/swarm memory import",
124166
124291
  description: "Use /swarm memory import to import legacy JSONL into SQLite"
@@ -124173,6 +124298,10 @@ async function initializeOpenCodeSwarm(ctx) {
124173
124298
  template: "/swarm curate",
124174
124299
  description: "Use /swarm curate to curate knowledge artifacts and entries"
124175
124300
  },
124301
+ "swarm-concurrency": {
124302
+ template: "/swarm concurrency $ARGUMENTS",
124303
+ description: "Use /swarm concurrency to manage runtime concurrency override for plan execution"
124304
+ },
124176
124305
  "swarm-turbo": {
124177
124306
  template: "/swarm turbo",
124178
124307
  description: "Use /swarm turbo to enable turbo mode for faster execution"
@@ -61,6 +61,8 @@ export interface SerializedAgentSession {
61
61
  sessionRehydratedAt?: number;
62
62
  /** Stage B completion tracking: per-task set of completed Stage B agents. Optional for backward compat with old snapshots. */
63
63
  stageBCompletion?: Record<string, string[]>;
64
+ /** Session-scoped concurrency override for max_concurrent_tasks (Issue #761) */
65
+ maxConcurrencyOverride?: number;
64
66
  }
65
67
  /**
66
68
  * Minimal interface for serialized InvocationWindow
package/dist/state.d.ts CHANGED
@@ -165,6 +165,10 @@ export interface AgentSessionState {
165
165
  leanTurboActive?: boolean;
166
166
  /** Current phase number when Lean Turbo is active (for durable state sync). */
167
167
  leanTurboCurrentPhase?: number;
168
+ /** Session-scoped concurrency override for max_concurrent_tasks (Issue #761).
169
+ * When set, overrides the plan's execution_profile.max_concurrent_tasks
170
+ * for delegation-gate guidance. Cleared on session reset. */
171
+ maxConcurrencyOverride?: number;
168
172
  /** Session-level QA gate overrides layered on top of the spec-level profile.
169
173
  * Overrides can only enable gates (true); false values are ignored by
170
174
  * getEffectiveGates. Cleared on session reset. Optional for backwards
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.38.0",
3
+ "version": "7.39.0",
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",