opencode-swarm 7.79.5 → 7.79.7

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.79.5",
55
+ version: "7.79.7",
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",
@@ -39424,6 +39424,51 @@ import * as path18 from "path";
39424
39424
  function normalizeText(text) {
39425
39425
  return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
39426
39426
  }
39427
+ function extractContextWords(text, word, contextWindow = 3) {
39428
+ const words = text.split(" ");
39429
+ const context = new Set;
39430
+ if (!word.includes(" ")) {
39431
+ let from = 0;
39432
+ let idx = words.indexOf(word, from);
39433
+ while (idx !== -1) {
39434
+ const start = Math.max(0, idx - contextWindow);
39435
+ const end = Math.min(words.length, idx + contextWindow + 1);
39436
+ for (let i2 = start;i2 < end; i2++) {
39437
+ if (i2 !== idx && words[i2] && words[i2].length > 0) {
39438
+ context.add(words[i2]);
39439
+ }
39440
+ }
39441
+ from = idx + 1;
39442
+ idx = words.indexOf(word, from);
39443
+ }
39444
+ return context;
39445
+ }
39446
+ const termLen = word.split(" ").length;
39447
+ let i = 0;
39448
+ while (i <= words.length - termLen) {
39449
+ const slice = words.slice(i, i + termLen).join(" ");
39450
+ if (slice === word) {
39451
+ const start = Math.max(0, i - contextWindow);
39452
+ const end = Math.min(words.length, i + termLen + contextWindow);
39453
+ for (let j = start;j < end; j++) {
39454
+ if (j < i || j >= i + termLen) {
39455
+ if (words[j] && words[j].length > 0) {
39456
+ context.add(words[j]);
39457
+ }
39458
+ }
39459
+ }
39460
+ i += termLen;
39461
+ } else {
39462
+ i += 1;
39463
+ }
39464
+ }
39465
+ return context;
39466
+ }
39467
+ function hasSignificantOverlap(set1, set22) {
39468
+ if (set1.size === 0 || set22.size === 0)
39469
+ return false;
39470
+ return [...set1].some((word) => set22.has(word));
39471
+ }
39427
39472
  function detectContradiction(candidate, existingLessons) {
39428
39473
  const candidateTags = inferTags(candidate);
39429
39474
  if (candidateTags.length === 0)
@@ -39436,10 +39481,20 @@ function detectContradiction(candidate, existingLessons) {
39436
39481
  continue;
39437
39482
  const existingNorm = normalizeText(existing);
39438
39483
  for (const [wordA, wordB] of NEGATION_PAIRS) {
39439
- const hasA = candidateNorm.includes(wordA) && existingNorm.includes(wordB);
39440
- const hasB = candidateNorm.includes(wordB) && existingNorm.includes(wordA);
39441
- if (hasA || hasB)
39442
- return true;
39484
+ if (candidateNorm.includes(wordA) && existingNorm.includes(wordB)) {
39485
+ const contextA = extractContextWords(candidateNorm, wordA);
39486
+ const contextB = extractContextWords(existingNorm, wordB);
39487
+ if (hasSignificantOverlap(contextA, contextB)) {
39488
+ return true;
39489
+ }
39490
+ }
39491
+ if (candidateNorm.includes(wordB) && existingNorm.includes(wordA)) {
39492
+ const contextB = extractContextWords(candidateNorm, wordB);
39493
+ const contextA = extractContextWords(existingNorm, wordA);
39494
+ if (hasSignificantOverlap(contextA, contextB)) {
39495
+ return true;
39496
+ }
39497
+ }
39443
39498
  }
39444
39499
  }
39445
39500
  return false;
@@ -40435,10 +40490,12 @@ function isSkillMaturityEligible(entry, opts, outcomes = entry.retrieval_outcome
40435
40490
  if (outcomeSignal < 0)
40436
40491
  return false;
40437
40492
  const strongOutcomes = hasStrongSkillOutcomeRecord(outcomes);
40493
+ if (outcomeSignal > 0 && strongOutcomes)
40494
+ return true;
40438
40495
  if (entry.confidence < opts.minConfidence && !strongOutcomes)
40439
40496
  return false;
40440
- const confirmations = (entry.confirmed_by ?? []).length;
40441
- return confirmations >= opts.minConfirmations || strongOutcomes;
40497
+ const distinctPhases = new Set((entry.confirmed_by ?? []).map((c) => c.phase_number).filter((p) => typeof p === "number")).size;
40498
+ return distinctPhases >= opts.minConfirmations || strongOutcomes;
40442
40499
  }
40443
40500
  function jaccardSimilarity(setA, setB) {
40444
40501
  const normA = setA.map((s) => s.toLowerCase());
@@ -41771,12 +41828,52 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
41771
41828
  if (!_internals17.existsSync(resolved)) {
41772
41829
  return { pruned: 0, remaining: 0 };
41773
41830
  }
41774
- const allEntries = readSkillUsageEntries(directory);
41775
- if (allEntries.length === 0) {
41831
+ const raw = _internals17.readFileSync(resolved, "utf-8");
41832
+ const lines = raw.split(`
41833
+ `);
41834
+ const entries = [];
41835
+ const preservedMarkers = [];
41836
+ for (const line of lines) {
41837
+ const trimmed = line.trim();
41838
+ if (!trimmed)
41839
+ continue;
41840
+ try {
41841
+ const parsed = JSON.parse(trimmed);
41842
+ const marker = parseFeedbackMarker(parsed);
41843
+ if (marker) {
41844
+ preservedMarkers.push(trimmed);
41845
+ continue;
41846
+ }
41847
+ const entry = parseSkillUsageEntry(parsed);
41848
+ if (entry) {
41849
+ entries.push(entry);
41850
+ }
41851
+ } catch {}
41852
+ }
41853
+ if (entries.length === 0) {
41854
+ if (preservedMarkers.length > 0) {
41855
+ const dir2 = path23.dirname(resolved);
41856
+ const tmpPath2 = path23.join(dir2, `skill-usage-${Date.now()}.tmp`);
41857
+ const content2 = preservedMarkers.join(`
41858
+ `).concat(preservedMarkers.length > 0 ? `
41859
+ ` : "");
41860
+ try {
41861
+ _internals17.writeFileSync(tmpPath2, content2, "utf-8");
41862
+ _internals17.renameSync(tmpPath2, resolved);
41863
+ } catch (writeErr) {
41864
+ const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
41865
+ try {
41866
+ if (_internals17.existsSync(tmpPath2)) {
41867
+ _internals17.writeFileSync(tmpPath2, "", "utf-8");
41868
+ }
41869
+ } catch {}
41870
+ return { pruned: 0, remaining: 0, error: msg };
41871
+ }
41872
+ }
41776
41873
  return { pruned: 0, remaining: 0 };
41777
41874
  }
41778
41875
  const groups = new Map;
41779
- for (const entry of allEntries) {
41876
+ for (const entry of entries) {
41780
41877
  const list = groups.get(entry.skillPath);
41781
41878
  if (list)
41782
41879
  list.push(entry);
@@ -41785,22 +41882,24 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
41785
41882
  }
41786
41883
  let pruned = 0;
41787
41884
  const surviving = [];
41788
- groups.forEach((entries) => {
41789
- if (entries.length <= maxEntriesPerSkill) {
41790
- surviving.push(...entries);
41885
+ groups.forEach((skillEntries) => {
41886
+ if (skillEntries.length <= maxEntriesPerSkill) {
41887
+ surviving.push(...skillEntries);
41791
41888
  return;
41792
41889
  }
41793
- entries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
41794
- const kept = entries.slice(0, maxEntriesPerSkill);
41795
- pruned += entries.length - kept.length;
41890
+ skillEntries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
41891
+ const kept = skillEntries.slice(0, maxEntriesPerSkill);
41892
+ pruned += skillEntries.length - kept.length;
41796
41893
  surviving.push(...kept);
41797
41894
  });
41798
41895
  if (pruned === 0) {
41799
- return { pruned: 0, remaining: allEntries.length };
41896
+ return { pruned: 0, remaining: entries.length };
41800
41897
  }
41801
41898
  const dir = path23.dirname(resolved);
41802
41899
  const tmpPath = path23.join(dir, `skill-usage-${Date.now()}.tmp`);
41803
- const content = surviving.map((e) => JSON.stringify(e)).join(`
41900
+ const entryLines = surviving.map((e) => JSON.stringify(e));
41901
+ const allLines = [...entryLines, ...preservedMarkers];
41902
+ const content = allLines.join(`
41804
41903
  `).concat(`
41805
41904
  `);
41806
41905
  try {
@@ -41813,7 +41912,7 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
41813
41912
  _internals17.writeFileSync(tmpPath, "", "utf-8");
41814
41913
  }
41815
41914
  } catch {}
41816
- return { pruned: 0, remaining: allEntries.length, error: msg };
41915
+ return { pruned: 0, remaining: entries.length, error: msg };
41817
41916
  }
41818
41917
  return { pruned, remaining: surviving.length };
41819
41918
  }
@@ -12,6 +12,20 @@ export declare const DANGEROUS_COMMAND_PATTERNS: RegExp[];
12
12
  export declare const SECURITY_DEGRADING_PATTERNS: RegExp[];
13
13
  export declare const INVISIBLE_FORMAT_CHARS: RegExp;
14
14
  export declare const INJECTION_PATTERNS: RegExp[];
15
+ /**
16
+ * Extract context words around each occurrence of a target word (single tokens within a window).
17
+ * Context window is 3 words before and after, excluding the target word itself.
18
+ * Handles multi-word terms (e.g. "must not", "don't use") by scanning word slices.
19
+ *
20
+ * Note: this is an exact-word-match heuristic. Synonyms (e.g. "use" / "utilize")
21
+ * will not match across lessons. The 3-token window is bounded; more distant
22
+ * negation attachments will not be detected as contradictions.
23
+ */
24
+ declare function extractContextWords(text: string, word: string, contextWindow?: number): Set<string>;
25
+ /**
26
+ * Check if two sets of words have significant overlap (at least one word in common).
27
+ */
28
+ declare function hasSignificantOverlap(set1: Set<string>, set2: Set<string>): boolean;
15
29
  export declare function validateLesson(candidate: string, existingLessons: string[], meta: {
16
30
  category: KnowledgeCategory;
17
31
  scope: string;
@@ -90,4 +104,6 @@ export declare const _internals: {
90
104
  auditEntryHealth: typeof auditEntryHealth;
91
105
  quarantineEntry: typeof quarantineEntry;
92
106
  restoreEntry: typeof restoreEntry;
107
+ extractContextWords: typeof extractContextWords;
108
+ hasSignificantOverlap: typeof hasSignificantOverlap;
93
109
  };
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.79.5",
72
+ version: "7.79.7",
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",
@@ -61771,6 +61771,51 @@ import * as path36 from "node:path";
61771
61771
  function normalizeText(text) {
61772
61772
  return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
61773
61773
  }
61774
+ function extractContextWords(text, word, contextWindow = 3) {
61775
+ const words = text.split(" ");
61776
+ const context = new Set;
61777
+ if (!word.includes(" ")) {
61778
+ let from = 0;
61779
+ let idx = words.indexOf(word, from);
61780
+ while (idx !== -1) {
61781
+ const start2 = Math.max(0, idx - contextWindow);
61782
+ const end = Math.min(words.length, idx + contextWindow + 1);
61783
+ for (let i3 = start2;i3 < end; i3++) {
61784
+ if (i3 !== idx && words[i3] && words[i3].length > 0) {
61785
+ context.add(words[i3]);
61786
+ }
61787
+ }
61788
+ from = idx + 1;
61789
+ idx = words.indexOf(word, from);
61790
+ }
61791
+ return context;
61792
+ }
61793
+ const termLen = word.split(" ").length;
61794
+ let i2 = 0;
61795
+ while (i2 <= words.length - termLen) {
61796
+ const slice = words.slice(i2, i2 + termLen).join(" ");
61797
+ if (slice === word) {
61798
+ const start2 = Math.max(0, i2 - contextWindow);
61799
+ const end = Math.min(words.length, i2 + termLen + contextWindow);
61800
+ for (let j = start2;j < end; j++) {
61801
+ if (j < i2 || j >= i2 + termLen) {
61802
+ if (words[j] && words[j].length > 0) {
61803
+ context.add(words[j]);
61804
+ }
61805
+ }
61806
+ }
61807
+ i2 += termLen;
61808
+ } else {
61809
+ i2 += 1;
61810
+ }
61811
+ }
61812
+ return context;
61813
+ }
61814
+ function hasSignificantOverlap(set1, set22) {
61815
+ if (set1.size === 0 || set22.size === 0)
61816
+ return false;
61817
+ return [...set1].some((word) => set22.has(word));
61818
+ }
61774
61819
  function detectContradiction(candidate, existingLessons) {
61775
61820
  const candidateTags = inferTags(candidate);
61776
61821
  if (candidateTags.length === 0)
@@ -61783,10 +61828,20 @@ function detectContradiction(candidate, existingLessons) {
61783
61828
  continue;
61784
61829
  const existingNorm = normalizeText(existing);
61785
61830
  for (const [wordA, wordB] of NEGATION_PAIRS) {
61786
- const hasA = candidateNorm.includes(wordA) && existingNorm.includes(wordB);
61787
- const hasB = candidateNorm.includes(wordB) && existingNorm.includes(wordA);
61788
- if (hasA || hasB)
61789
- return true;
61831
+ if (candidateNorm.includes(wordA) && existingNorm.includes(wordB)) {
61832
+ const contextA = extractContextWords(candidateNorm, wordA);
61833
+ const contextB = extractContextWords(existingNorm, wordB);
61834
+ if (hasSignificantOverlap(contextA, contextB)) {
61835
+ return true;
61836
+ }
61837
+ }
61838
+ if (candidateNorm.includes(wordB) && existingNorm.includes(wordA)) {
61839
+ const contextB = extractContextWords(candidateNorm, wordB);
61840
+ const contextA = extractContextWords(existingNorm, wordA);
61841
+ if (hasSignificantOverlap(contextA, contextB)) {
61842
+ return true;
61843
+ }
61844
+ }
61790
61845
  }
61791
61846
  }
61792
61847
  return false;
@@ -62806,10 +62861,12 @@ function isSkillMaturityEligible(entry, opts, outcomes = entry.retrieval_outcome
62806
62861
  if (outcomeSignal < 0)
62807
62862
  return false;
62808
62863
  const strongOutcomes = hasStrongSkillOutcomeRecord(outcomes);
62864
+ if (outcomeSignal > 0 && strongOutcomes)
62865
+ return true;
62809
62866
  if (entry.confidence < opts.minConfidence && !strongOutcomes)
62810
62867
  return false;
62811
- const confirmations = (entry.confirmed_by ?? []).length;
62812
- return confirmations >= opts.minConfirmations || strongOutcomes;
62868
+ const distinctPhases = new Set((entry.confirmed_by ?? []).map((c) => c.phase_number).filter((p) => typeof p === "number")).size;
62869
+ return distinctPhases >= opts.minConfirmations || strongOutcomes;
62813
62870
  }
62814
62871
  function jaccardSimilarity(setA, setB) {
62815
62872
  const normA = setA.map((s) => s.toLowerCase());
@@ -64410,12 +64467,52 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
64410
64467
  if (!_internals27.existsSync(resolved)) {
64411
64468
  return { pruned: 0, remaining: 0 };
64412
64469
  }
64413
- const allEntries = readSkillUsageEntries(directory);
64414
- if (allEntries.length === 0) {
64470
+ const raw = _internals27.readFileSync(resolved, "utf-8");
64471
+ const lines = raw.split(`
64472
+ `);
64473
+ const entries = [];
64474
+ const preservedMarkers = [];
64475
+ for (const line of lines) {
64476
+ const trimmed = line.trim();
64477
+ if (!trimmed)
64478
+ continue;
64479
+ try {
64480
+ const parsed = JSON.parse(trimmed);
64481
+ const marker = parseFeedbackMarker(parsed);
64482
+ if (marker) {
64483
+ preservedMarkers.push(trimmed);
64484
+ continue;
64485
+ }
64486
+ const entry = parseSkillUsageEntry(parsed);
64487
+ if (entry) {
64488
+ entries.push(entry);
64489
+ }
64490
+ } catch {}
64491
+ }
64492
+ if (entries.length === 0) {
64493
+ if (preservedMarkers.length > 0) {
64494
+ const dir2 = path41.dirname(resolved);
64495
+ const tmpPath2 = path41.join(dir2, `skill-usage-${Date.now()}.tmp`);
64496
+ const content2 = preservedMarkers.join(`
64497
+ `).concat(preservedMarkers.length > 0 ? `
64498
+ ` : "");
64499
+ try {
64500
+ _internals27.writeFileSync(tmpPath2, content2, "utf-8");
64501
+ _internals27.renameSync(tmpPath2, resolved);
64502
+ } catch (writeErr) {
64503
+ const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
64504
+ try {
64505
+ if (_internals27.existsSync(tmpPath2)) {
64506
+ _internals27.writeFileSync(tmpPath2, "", "utf-8");
64507
+ }
64508
+ } catch {}
64509
+ return { pruned: 0, remaining: 0, error: msg };
64510
+ }
64511
+ }
64415
64512
  return { pruned: 0, remaining: 0 };
64416
64513
  }
64417
64514
  const groups = new Map;
64418
- for (const entry of allEntries) {
64515
+ for (const entry of entries) {
64419
64516
  const list = groups.get(entry.skillPath);
64420
64517
  if (list)
64421
64518
  list.push(entry);
@@ -64424,22 +64521,24 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
64424
64521
  }
64425
64522
  let pruned = 0;
64426
64523
  const surviving = [];
64427
- groups.forEach((entries) => {
64428
- if (entries.length <= maxEntriesPerSkill) {
64429
- surviving.push(...entries);
64524
+ groups.forEach((skillEntries) => {
64525
+ if (skillEntries.length <= maxEntriesPerSkill) {
64526
+ surviving.push(...skillEntries);
64430
64527
  return;
64431
64528
  }
64432
- entries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
64433
- const kept = entries.slice(0, maxEntriesPerSkill);
64434
- pruned += entries.length - kept.length;
64529
+ skillEntries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
64530
+ const kept = skillEntries.slice(0, maxEntriesPerSkill);
64531
+ pruned += skillEntries.length - kept.length;
64435
64532
  surviving.push(...kept);
64436
64533
  });
64437
64534
  if (pruned === 0) {
64438
- return { pruned: 0, remaining: allEntries.length };
64535
+ return { pruned: 0, remaining: entries.length };
64439
64536
  }
64440
64537
  const dir = path41.dirname(resolved);
64441
64538
  const tmpPath = path41.join(dir, `skill-usage-${Date.now()}.tmp`);
64442
- const content = surviving.map((e) => JSON.stringify(e)).join(`
64539
+ const entryLines = surviving.map((e) => JSON.stringify(e));
64540
+ const allLines = [...entryLines, ...preservedMarkers];
64541
+ const content = allLines.join(`
64443
64542
  `).concat(`
64444
64543
  `);
64445
64544
  try {
@@ -64452,7 +64551,7 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
64452
64551
  _internals27.writeFileSync(tmpPath, "", "utf-8");
64453
64552
  }
64454
64553
  } catch {}
64455
- return { pruned: 0, remaining: allEntries.length, error: msg };
64554
+ return { pruned: 0, remaining: entries.length, error: msg };
64456
64555
  }
64457
64556
  return { pruned, remaining: surviving.length };
64458
64557
  }
@@ -65362,7 +65461,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config3, know
65362
65461
  try {
65363
65462
  const skillModule = await Promise.resolve().then(() => (init_skill_generator(), exports_skill_generator));
65364
65463
  for (const cand of skillCandidates) {
65365
- if (cand.confidence < (config3.min_skill_confidence ?? 0.85)) {
65464
+ if (cand.confidence < (config3.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
65366
65465
  continue;
65367
65466
  }
65368
65467
  await skillModule.generateSkills({
@@ -98327,6 +98426,11 @@ Every listed directive ID MUST appear exactly once. If a directive carries a ver
98327
98426
  FIXES: required changes if rejected
98328
98427
  Use INFO only inside ISSUES for non-blocking suggestions. RISK reflects the highest blocking severity, so it never uses INFO.
98329
98428
 
98429
+ ## OUTPUT ORDER FOR SKILL COMPLIANCE (when applicable)
98430
+ When SKILLS_USED_BY_CODER is provided, output TASK: immediately followed by SKILL_COMPLIANCE to ensure proper attribution:
98431
+ TASK: <task-id-or-unknown>
98432
+ SKILL_COMPLIANCE: <verdict> — <details>
98433
+
98330
98434
  ## RULES
98331
98435
  - Be specific with line numbers
98332
98436
  - Only flag real issues, not theoretical
@@ -131064,7 +131168,7 @@ async function withTurboStateLock(directory, sessionID, fn2, timeoutMs = 30000)
131064
131168
  } catch (acquireErr) {
131065
131169
  console.warn(`[lean-turbo] state lock acquisition error for ${sessionID} (${lockPath}), will retry: ${acquireErr instanceof Error ? acquireErr.message : String(acquireErr)}`);
131066
131170
  }
131067
- if (result && result.acquired) {
131171
+ if (result?.acquired) {
131068
131172
  const lock = result.lock;
131069
131173
  try {
131070
131174
  return await fn2();
@@ -134666,18 +134770,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
134666
134770
  safeWarn("[phase_complete] Design-doc drift check error (non-blocking):", docDriftError);
134667
134771
  }
134668
134772
  try {
134669
- const markerPath = validateSwarmPath(dir, "skill-usage-last-processed.json");
134670
- let sinceTimestamp;
134671
- try {
134672
- const markerData = JSON.parse(fs111.readFileSync(markerPath, "utf-8"));
134673
- sinceTimestamp = markerData.lastProcessedTimestamp;
134674
- } catch {}
134675
- const feedbackResult = await applySkillUsageFeedback(dir, {
134676
- sinceTimestamp
134677
- });
134678
- try {
134679
- fs111.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
134680
- } catch {}
134773
+ const feedbackResult = await applySkillUsageFeedback(dir);
134681
134774
  if (feedbackResult.processed > 0) {
134682
134775
  const sessionState = swarmState.agentSessions.get(sessionID);
134683
134776
  if (sessionState) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.79.5",
3
+ "version": "7.79.7",
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",