opencode-swarm 7.62.0 → 7.62.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
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.62.0",
55
+ version: "7.62.1",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -22486,6 +22486,23 @@ function resetSwarmState() {
22486
22486
  resetStandardWorktreeIsolationState();
22487
22487
  _councilDisagreementWarned.clear();
22488
22488
  }
22489
+ function resetSwarmStatePreservingSingletons() {
22490
+ const preservedOpencodeClient = swarmState.opencodeClient;
22491
+ const preservedFullAutoEnabledInConfig = swarmState.fullAutoEnabledInConfig;
22492
+ const preservedCuratorInitAgentNames = swarmState.curatorInitAgentNames;
22493
+ const preservedCuratorPhaseAgentNames = swarmState.curatorPhaseAgentNames;
22494
+ const preservedSkillImproverAgentNames = swarmState.skillImproverAgentNames;
22495
+ const preservedSpecWriterAgentNames = swarmState.specWriterAgentNames;
22496
+ const preservedGeneratedAgentNames = swarmState.generatedAgentNames;
22497
+ resetSwarmState();
22498
+ swarmState.opencodeClient = preservedOpencodeClient;
22499
+ swarmState.fullAutoEnabledInConfig = preservedFullAutoEnabledInConfig;
22500
+ swarmState.curatorInitAgentNames = preservedCuratorInitAgentNames;
22501
+ swarmState.curatorPhaseAgentNames = preservedCuratorPhaseAgentNames;
22502
+ swarmState.skillImproverAgentNames = preservedSkillImproverAgentNames;
22503
+ swarmState.specWriterAgentNames = preservedSpecWriterAgentNames;
22504
+ swarmState.generatedAgentNames = preservedGeneratedAgentNames;
22505
+ }
22489
22506
  function getAgentSession(sessionId) {
22490
22507
  return swarmState.agentSessions.get(sessionId);
22491
22508
  }
@@ -39826,6 +39843,7 @@ var init_write_retro = __esm(() => {
39826
39843
  });
39827
39844
 
39828
39845
  // src/commands/close.ts
39846
+ import * as fsSync2 from "fs";
39829
39847
  import { promises as fs10 } from "fs";
39830
39848
  import path21 from "path";
39831
39849
  async function runAbortableSkillReview(req, timeoutMs) {
@@ -39861,6 +39879,28 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
39861
39879
  return Number.isFinite(createdAtMs) && createdAtMs >= sessionStartMs;
39862
39880
  }).length;
39863
39881
  }
39882
+ async function copyDirRecursive(src, dest) {
39883
+ let count = 0;
39884
+ const entries = await fs10.readdir(src);
39885
+ await fs10.mkdir(dest, { recursive: true });
39886
+ for (const entry of entries) {
39887
+ const srcEntry = path21.join(src, entry);
39888
+ const destEntry = path21.join(dest, entry);
39889
+ try {
39890
+ const stat2 = await fs10.stat(srcEntry);
39891
+ if (stat2.isDirectory()) {
39892
+ const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
39893
+ count += subCount;
39894
+ } else {
39895
+ try {
39896
+ await fs10.copyFile(srcEntry, destEntry);
39897
+ count++;
39898
+ } catch {}
39899
+ }
39900
+ } catch {}
39901
+ }
39902
+ return count;
39903
+ }
39864
39904
  function guaranteeAllPlansComplete(planData) {
39865
39905
  const closedPhaseIds = [];
39866
39906
  const closedTaskIds = [];
@@ -39882,8 +39922,18 @@ function guaranteeAllPlansComplete(planData) {
39882
39922
  return { closedPhaseIds, closedTaskIds };
39883
39923
  }
39884
39924
  async function handleCloseCommand(directory, args, options = {}) {
39885
- const planPath = validateSwarmPath(directory, "plan.json");
39886
39925
  const swarmDir = path21.join(directory, ".swarm");
39926
+ try {
39927
+ const stat2 = fsSync2.lstatSync(swarmDir);
39928
+ if (stat2.isSymbolicLink()) {
39929
+ return `\u274C Refused: .swarm/ is a symlink or junction. Refusing to operate on a redirected directory for safety.`;
39930
+ }
39931
+ } catch (err) {
39932
+ if (err?.code !== "ENOENT") {
39933
+ throw err;
39934
+ }
39935
+ }
39936
+ const planPath = validateSwarmPath(directory, "plan.json");
39887
39937
  let planExists = false;
39888
39938
  let planData = {
39889
39939
  title: path21.basename(directory) || "Ad-hoc session",
@@ -40165,31 +40215,12 @@ async function handleCloseCommand(directory, args, options = {}) {
40165
40215
  const srcDir = path21.join(swarmDir, dirName);
40166
40216
  const destDir = path21.join(archiveDir, dirName);
40167
40217
  try {
40168
- const entries = await fs10.readdir(srcDir);
40169
- if (entries.length > 0) {
40170
- await fs10.mkdir(destDir, { recursive: true });
40171
- for (const entry of entries) {
40172
- const srcEntry = path21.join(srcDir, entry);
40173
- const destEntry = path21.join(destDir, entry);
40174
- try {
40175
- const stat2 = await fs10.stat(srcEntry);
40176
- if (stat2.isDirectory()) {
40177
- await fs10.mkdir(destEntry, { recursive: true });
40178
- const subEntries = await fs10.readdir(srcEntry);
40179
- for (const sub of subEntries) {
40180
- await fs10.copyFile(path21.join(srcEntry, sub), path21.join(destEntry, sub)).catch(() => {});
40181
- }
40182
- } else {
40183
- await fs10.copyFile(srcEntry, destEntry);
40184
- }
40185
- archivedFileCount++;
40186
- } catch {}
40187
- }
40188
- }
40218
+ const copied = await copyDirRecursive(srcDir, destDir);
40219
+ archivedFileCount += copied;
40189
40220
  archivedActiveStateDirs.add(dirName);
40190
40221
  } catch {}
40191
40222
  }
40192
- archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
40223
+ archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}-${suffix}/`;
40193
40224
  } catch (archiveError) {
40194
40225
  warnings.push(`Archive creation failed: ${archiveError instanceof Error ? archiveError.message : String(archiveError)}`);
40195
40226
  archiveResult = "Archive creation failed (see warnings)";
@@ -40261,6 +40292,20 @@ async function handleCloseCommand(directory, args, options = {}) {
40261
40292
  }
40262
40293
  }
40263
40294
  }
40295
+ let tmpFilesRemoved = 0;
40296
+ try {
40297
+ const swarmFiles = await fs10.readdir(swarmDir);
40298
+ const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
40299
+ for (const tmp of tmpFiles) {
40300
+ try {
40301
+ await fs10.unlink(path21.join(swarmDir, tmp));
40302
+ tmpFilesRemoved++;
40303
+ } catch {}
40304
+ }
40305
+ } catch {}
40306
+ if (tmpFilesRemoved > 0) {
40307
+ cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
40308
+ }
40264
40309
  clearAllScopes(directory);
40265
40310
  const contextPath = path21.join(swarmDir, "context.md");
40266
40311
  const contextContent = [
@@ -40367,17 +40412,7 @@ async function handleCloseCommand(directory, args, options = {}) {
40367
40412
  warnings.push(`Failed to write close-summary.md: ${msg}`);
40368
40413
  console.warn("[close-command] Failed to write close-summary.md:", error93);
40369
40414
  }
40370
- const preservedClient = swarmState.opencodeClient;
40371
- const preservedFullAutoFlag = swarmState.fullAutoEnabledInConfig;
40372
- const preservedCuratorInitNames = swarmState.curatorInitAgentNames;
40373
- const preservedCuratorPhaseNames = swarmState.curatorPhaseAgentNames;
40374
- const preservedSkillImproverAgentNames = swarmState.skillImproverAgentNames;
40375
- resetSwarmState();
40376
- swarmState.opencodeClient = preservedClient;
40377
- swarmState.fullAutoEnabledInConfig = preservedFullAutoFlag;
40378
- swarmState.curatorInitAgentNames = preservedCuratorInitNames;
40379
- swarmState.curatorPhaseAgentNames = preservedCuratorPhaseNames;
40380
- swarmState.skillImproverAgentNames = preservedSkillImproverAgentNames;
40415
+ resetSwarmStatePreservingSingletons();
40381
40416
  const retroWarnings = warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
40382
40417
  const otherWarnings = warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
40383
40418
  let warningMsg = "";
@@ -58504,14 +58539,14 @@ var init_context_budget_service = __esm(() => {
58504
58539
  });
58505
58540
 
58506
58541
  // src/services/status-service.ts
58507
- import * as fsSync2 from "fs";
58542
+ import * as fsSync3 from "fs";
58508
58543
  import * as path55 from "path";
58509
58544
  function readSpecStalenessSnapshot(directory) {
58510
58545
  try {
58511
58546
  const p = path55.join(directory, ".swarm", "spec-staleness.json");
58512
- if (!fsSync2.existsSync(p))
58547
+ if (!fsSync3.existsSync(p))
58513
58548
  return { stale: false };
58514
- const raw = fsSync2.readFileSync(p, "utf-8");
58549
+ const raw = fsSync3.readFileSync(p, "utf-8");
58515
58550
  const parsed = JSON.parse(raw);
58516
58551
  return {
58517
58552
  stale: true,
@@ -1,3 +1,17 @@
1
+ interface PlanPhase {
2
+ id: number;
3
+ name: string;
4
+ status: string;
5
+ tasks: Array<{
6
+ id: string;
7
+ status: string;
8
+ close_reason?: string;
9
+ }>;
10
+ }
11
+ interface PlanData {
12
+ title: string;
13
+ phases: PlanPhase[];
14
+ }
1
15
  interface CloseCommandOptions {
2
16
  sessionID?: string;
3
17
  skillReviewTimeoutMs?: number;
@@ -6,6 +20,16 @@ interface CloseKnowledgeEntry {
6
20
  created_at?: string;
7
21
  }
8
22
  declare function countSessionKnowledgeEntries(entries: CloseKnowledgeEntry[], sessionStart: string | undefined, fallbackCount: number): number;
23
+ declare function copyDirRecursive(src: string, dest: string): Promise<number>;
24
+ /**
25
+ * Guarantee all phases and tasks in a plan are marked complete/closed.
26
+ * Mutates planData in place. Returns actual IDs of newly closed phases and
27
+ * tasks so the caller can track only genuinely new closures (idempotent).
28
+ */
29
+ declare function guaranteeAllPlansComplete(planData: PlanData): {
30
+ closedPhaseIds: number[];
31
+ closedTaskIds: string[];
32
+ };
9
33
  /**
10
34
  * Handles /swarm close command - performs full terminal session finalization:
11
35
  * 0. Guarantee: mark all incomplete phases/tasks as closed
@@ -20,5 +44,7 @@ export declare function handleCloseCommand(directory: string, args: string[], op
20
44
  export declare const _internals: {
21
45
  countSessionKnowledgeEntries: typeof countSessionKnowledgeEntries;
22
46
  CLOSE_SKILL_REVIEW_TIMEOUT_MS: number;
47
+ guaranteeAllPlansComplete: typeof guaranteeAllPlansComplete;
48
+ copyDirRecursive: typeof copyDirRecursive;
23
49
  };
24
50
  export {};
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.62.0",
72
+ version: "7.62.1",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -42974,6 +42974,7 @@ __export(exports_state, {
42974
42974
  startAgentSession: () => startAgentSession,
42975
42975
  setSessionEnvironment: () => setSessionEnvironment,
42976
42976
  setCriticalShownIds: () => setCriticalShownIds,
42977
+ resetSwarmStatePreservingSingletons: () => resetSwarmStatePreservingSingletons,
42977
42978
  resetSwarmState: () => resetSwarmState,
42978
42979
  rehydrateSessionFromDisk: () => rehydrateSessionFromDisk,
42979
42980
  recordStageBCompletion: () => recordStageBCompletion,
@@ -43038,6 +43039,23 @@ function resetSwarmState() {
43038
43039
  resetStandardWorktreeIsolationState();
43039
43040
  _councilDisagreementWarned.clear();
43040
43041
  }
43042
+ function resetSwarmStatePreservingSingletons() {
43043
+ const preservedOpencodeClient = swarmState.opencodeClient;
43044
+ const preservedFullAutoEnabledInConfig = swarmState.fullAutoEnabledInConfig;
43045
+ const preservedCuratorInitAgentNames = swarmState.curatorInitAgentNames;
43046
+ const preservedCuratorPhaseAgentNames = swarmState.curatorPhaseAgentNames;
43047
+ const preservedSkillImproverAgentNames = swarmState.skillImproverAgentNames;
43048
+ const preservedSpecWriterAgentNames = swarmState.specWriterAgentNames;
43049
+ const preservedGeneratedAgentNames = swarmState.generatedAgentNames;
43050
+ resetSwarmState();
43051
+ swarmState.opencodeClient = preservedOpencodeClient;
43052
+ swarmState.fullAutoEnabledInConfig = preservedFullAutoEnabledInConfig;
43053
+ swarmState.curatorInitAgentNames = preservedCuratorInitAgentNames;
43054
+ swarmState.curatorPhaseAgentNames = preservedCuratorPhaseAgentNames;
43055
+ swarmState.skillImproverAgentNames = preservedSkillImproverAgentNames;
43056
+ swarmState.specWriterAgentNames = preservedSpecWriterAgentNames;
43057
+ swarmState.generatedAgentNames = preservedGeneratedAgentNames;
43058
+ }
43041
43059
  function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, directory) {
43042
43060
  const now = Date.now();
43043
43061
  const staleIds = [];
@@ -62745,6 +62763,7 @@ var init_write_retro = __esm(() => {
62745
62763
  });
62746
62764
 
62747
62765
  // src/commands/close.ts
62766
+ import * as fsSync3 from "node:fs";
62748
62767
  import { promises as fs20 } from "node:fs";
62749
62768
  import path35 from "node:path";
62750
62769
  async function runAbortableSkillReview(req, timeoutMs) {
@@ -62780,6 +62799,28 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
62780
62799
  return Number.isFinite(createdAtMs) && createdAtMs >= sessionStartMs;
62781
62800
  }).length;
62782
62801
  }
62802
+ async function copyDirRecursive(src, dest) {
62803
+ let count = 0;
62804
+ const entries = await fs20.readdir(src);
62805
+ await fs20.mkdir(dest, { recursive: true });
62806
+ for (const entry of entries) {
62807
+ const srcEntry = path35.join(src, entry);
62808
+ const destEntry = path35.join(dest, entry);
62809
+ try {
62810
+ const stat3 = await fs20.stat(srcEntry);
62811
+ if (stat3.isDirectory()) {
62812
+ const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
62813
+ count += subCount;
62814
+ } else {
62815
+ try {
62816
+ await fs20.copyFile(srcEntry, destEntry);
62817
+ count++;
62818
+ } catch {}
62819
+ }
62820
+ } catch {}
62821
+ }
62822
+ return count;
62823
+ }
62783
62824
  function guaranteeAllPlansComplete(planData) {
62784
62825
  const closedPhaseIds = [];
62785
62826
  const closedTaskIds = [];
@@ -62801,8 +62842,18 @@ function guaranteeAllPlansComplete(planData) {
62801
62842
  return { closedPhaseIds, closedTaskIds };
62802
62843
  }
62803
62844
  async function handleCloseCommand(directory, args2, options = {}) {
62804
- const planPath = validateSwarmPath(directory, "plan.json");
62805
62845
  const swarmDir = path35.join(directory, ".swarm");
62846
+ try {
62847
+ const stat3 = fsSync3.lstatSync(swarmDir);
62848
+ if (stat3.isSymbolicLink()) {
62849
+ return `❌ Refused: .swarm/ is a symlink or junction. Refusing to operate on a redirected directory for safety.`;
62850
+ }
62851
+ } catch (err2) {
62852
+ if (err2?.code !== "ENOENT") {
62853
+ throw err2;
62854
+ }
62855
+ }
62856
+ const planPath = validateSwarmPath(directory, "plan.json");
62806
62857
  let planExists = false;
62807
62858
  let planData = {
62808
62859
  title: path35.basename(directory) || "Ad-hoc session",
@@ -63084,31 +63135,12 @@ async function handleCloseCommand(directory, args2, options = {}) {
63084
63135
  const srcDir = path35.join(swarmDir, dirName);
63085
63136
  const destDir = path35.join(archiveDir, dirName);
63086
63137
  try {
63087
- const entries = await fs20.readdir(srcDir);
63088
- if (entries.length > 0) {
63089
- await fs20.mkdir(destDir, { recursive: true });
63090
- for (const entry of entries) {
63091
- const srcEntry = path35.join(srcDir, entry);
63092
- const destEntry = path35.join(destDir, entry);
63093
- try {
63094
- const stat3 = await fs20.stat(srcEntry);
63095
- if (stat3.isDirectory()) {
63096
- await fs20.mkdir(destEntry, { recursive: true });
63097
- const subEntries = await fs20.readdir(srcEntry);
63098
- for (const sub of subEntries) {
63099
- await fs20.copyFile(path35.join(srcEntry, sub), path35.join(destEntry, sub)).catch(() => {});
63100
- }
63101
- } else {
63102
- await fs20.copyFile(srcEntry, destEntry);
63103
- }
63104
- archivedFileCount++;
63105
- } catch {}
63106
- }
63107
- }
63138
+ const copied = await copyDirRecursive(srcDir, destDir);
63139
+ archivedFileCount += copied;
63108
63140
  archivedActiveStateDirs.add(dirName);
63109
63141
  } catch {}
63110
63142
  }
63111
- archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
63143
+ archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}-${suffix}/`;
63112
63144
  } catch (archiveError) {
63113
63145
  warnings.push(`Archive creation failed: ${archiveError instanceof Error ? archiveError.message : String(archiveError)}`);
63114
63146
  archiveResult = "Archive creation failed (see warnings)";
@@ -63180,6 +63212,20 @@ async function handleCloseCommand(directory, args2, options = {}) {
63180
63212
  }
63181
63213
  }
63182
63214
  }
63215
+ let tmpFilesRemoved = 0;
63216
+ try {
63217
+ const swarmFiles = await fs20.readdir(swarmDir);
63218
+ const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
63219
+ for (const tmp of tmpFiles) {
63220
+ try {
63221
+ await fs20.unlink(path35.join(swarmDir, tmp));
63222
+ tmpFilesRemoved++;
63223
+ } catch {}
63224
+ }
63225
+ } catch {}
63226
+ if (tmpFilesRemoved > 0) {
63227
+ cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
63228
+ }
63183
63229
  clearAllScopes(directory);
63184
63230
  const contextPath = path35.join(swarmDir, "context.md");
63185
63231
  const contextContent = [
@@ -63286,17 +63332,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
63286
63332
  warnings.push(`Failed to write close-summary.md: ${msg}`);
63287
63333
  console.warn("[close-command] Failed to write close-summary.md:", error93);
63288
63334
  }
63289
- const preservedClient = swarmState.opencodeClient;
63290
- const preservedFullAutoFlag = swarmState.fullAutoEnabledInConfig;
63291
- const preservedCuratorInitNames = swarmState.curatorInitAgentNames;
63292
- const preservedCuratorPhaseNames = swarmState.curatorPhaseAgentNames;
63293
- const preservedSkillImproverAgentNames = swarmState.skillImproverAgentNames;
63294
- resetSwarmState();
63295
- swarmState.opencodeClient = preservedClient;
63296
- swarmState.fullAutoEnabledInConfig = preservedFullAutoFlag;
63297
- swarmState.curatorInitAgentNames = preservedCuratorInitNames;
63298
- swarmState.curatorPhaseAgentNames = preservedCuratorPhaseNames;
63299
- swarmState.skillImproverAgentNames = preservedSkillImproverAgentNames;
63335
+ resetSwarmStatePreservingSingletons();
63300
63336
  const retroWarnings = warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
63301
63337
  const otherWarnings = warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
63302
63338
  let warningMsg = "";
@@ -82911,14 +82947,14 @@ var init_context_budget_service = __esm(() => {
82911
82947
  });
82912
82948
 
82913
82949
  // src/services/status-service.ts
82914
- import * as fsSync3 from "node:fs";
82950
+ import * as fsSync4 from "node:fs";
82915
82951
  import * as path73 from "node:path";
82916
82952
  function readSpecStalenessSnapshot(directory) {
82917
82953
  try {
82918
82954
  const p = path73.join(directory, ".swarm", "spec-staleness.json");
82919
- if (!fsSync3.existsSync(p))
82955
+ if (!fsSync4.existsSync(p))
82920
82956
  return { stale: false };
82921
- const raw = fsSync3.readFileSync(p, "utf-8");
82957
+ const raw = fsSync4.readFileSync(p, "utf-8");
82922
82958
  const parsed = JSON.parse(raw);
82923
82959
  return {
82924
82960
  stale: true,
@@ -98885,7 +98921,7 @@ import * as path97 from "node:path";
98885
98921
  // src/tools/repo-graph/builder.ts
98886
98922
  init_logger();
98887
98923
  init_path_security();
98888
- import * as fsSync4 from "node:fs";
98924
+ import * as fsSync5 from "node:fs";
98889
98925
  import { existsSync as existsSync56, realpathSync as realpathSync12 } from "node:fs";
98890
98926
  import * as fsPromises5 from "node:fs/promises";
98891
98927
  import * as os14 from "node:os";
@@ -99891,11 +99927,11 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
99891
99927
  let content;
99892
99928
  let fileStats;
99893
99929
  try {
99894
- fileStats = fsSync4.statSync(filePath);
99930
+ fileStats = fsSync5.statSync(filePath);
99895
99931
  if (fileStats.size > maxFileSize) {
99896
99932
  return { node: null, edges: [] };
99897
99933
  }
99898
- content = fsSync4.readFileSync(filePath, "utf-8");
99934
+ content = fsSync5.readFileSync(filePath, "utf-8");
99899
99935
  } catch {
99900
99936
  return { node: null, edges: [] };
99901
99937
  }
package/dist/state.d.ts CHANGED
@@ -334,6 +334,23 @@ export declare const swarmState: {
334
334
  * Reset all state to initial values - useful for testing
335
335
  */
336
336
  export declare function resetSwarmState(): void;
337
+ /**
338
+ * Reset swarm state while preserving the 7 module-scoped singletons that are
339
+ * populated once at plugin init and must survive a /swarm close + re-init
340
+ * within the same process lifetime.
341
+ *
342
+ * The preserved fields are:
343
+ * - opencodeClient (SDK client for curator/full-auto delegation)
344
+ * - fullAutoEnabledInConfig (config flag read at init)
345
+ * - curatorInitAgentNames, curatorPhaseAgentNames (curator registry)
346
+ * - skillImproverAgentNames, specWriterAgentNames (skill/spec registry)
347
+ * - generatedAgentNames (full-auto delegation guard registry)
348
+ *
349
+ * Implementation: save all 7 to locals, call resetSwarmState(), restore all 7.
350
+ * Synchronous (matches resetSwarmState contract). Errors from resetSwarmState
351
+ * propagate to caller (no try/catch wrapper).
352
+ */
353
+ export declare function resetSwarmStatePreservingSingletons(): void;
337
354
  /**
338
355
  * Start a new agent session with initialized guardrail state.
339
356
  * Also removes any stale sessions older than staleDurationMs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.62.0",
3
+ "version": "7.62.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",