opencode-swarm 7.24.0 → 7.24.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.24.0",
37
+ version: "7.24.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",
@@ -35267,6 +35267,20 @@ function normalizeEntry(raw) {
35267
35267
  ro.failed_after_shown_count = typeof ro.failed_after_count === "number" ? ro.failed_after_count : 0;
35268
35268
  }
35269
35269
  }
35270
+ try {
35271
+ if (typeof obj.encounter_score !== "number" || Number.isNaN(obj.encounter_score)) {
35272
+ obj.encounter_score = 0;
35273
+ }
35274
+ } catch {
35275
+ try {
35276
+ Object.defineProperty(obj, "encounter_score", {
35277
+ value: 0,
35278
+ writable: true,
35279
+ configurable: true,
35280
+ enumerable: true
35281
+ });
35282
+ } catch {}
35283
+ }
35270
35284
  const arrayFields = [
35271
35285
  "triggers",
35272
35286
  "required_actions",
@@ -35826,12 +35840,26 @@ import path12 from "path";
35826
35840
  function isAlreadyInHive(entry, hiveEntries, threshold) {
35827
35841
  return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
35828
35842
  }
35829
- function countDistinctPhases(confirmedBy) {
35843
+ function isHiveEligible(entry, autoPromoteDays) {
35830
35844
  const phaseNumbers = new Set;
35831
- for (const record3 of confirmedBy) {
35832
- phaseNumbers.add(record3.phase_number);
35845
+ for (const record3 of entry.confirmed_by ?? []) {
35846
+ if (record3 && typeof record3.phase_number === "number") {
35847
+ phaseNumbers.add(record3.phase_number);
35848
+ }
35833
35849
  }
35834
- return phaseNumbers.size;
35850
+ if (entry.hive_eligible === true && phaseNumbers.size >= 3) {
35851
+ return true;
35852
+ }
35853
+ if ((entry.tags ?? []).includes("hive-fast-track")) {
35854
+ return true;
35855
+ }
35856
+ const createdMs = Date.parse(entry.created_at);
35857
+ const ageMs = Number.isFinite(createdMs) ? Date.now() - createdMs : 0;
35858
+ const ageThresholdMs = autoPromoteDays * 86400000;
35859
+ if (ageMs >= ageThresholdMs) {
35860
+ return true;
35861
+ }
35862
+ return false;
35835
35863
  }
35836
35864
  function countDistinctProjects(confirmedBy) {
35837
35865
  const projectNames = new Set;
@@ -35849,12 +35877,6 @@ function calculateEncounterScore(currentScore, isSameProject, config3) {
35849
35877
  const newScore = currentScore + increment;
35850
35878
  return Math.min(Math.max(newScore, config3.min_encounter_score), config3.max_encounter_score);
35851
35879
  }
35852
- function getEntryAgeMs(createdAt) {
35853
- const createdTime = new Date(createdAt).getTime();
35854
- if (Number.isNaN(createdTime))
35855
- return 0;
35856
- return Date.now() - createdTime;
35857
- }
35858
35880
  async function checkHivePromotions(swarmEntries, config3) {
35859
35881
  let newPromotions = 0;
35860
35882
  let encountersIncremented = 0;
@@ -35873,19 +35895,7 @@ async function checkHivePromotions(swarmEntries, config3) {
35873
35895
  if (isAlreadyInHive(swarmEntry, hiveEntries, config3.dedup_threshold)) {
35874
35896
  continue;
35875
35897
  }
35876
- let shouldPromote = false;
35877
- if (swarmEntry.hive_eligible === true && countDistinctPhases(swarmEntry.confirmed_by) >= 3) {
35878
- shouldPromote = true;
35879
- }
35880
- if (swarmEntry.tags.includes("hive-fast-track")) {
35881
- shouldPromote = true;
35882
- }
35883
- const ageMs = getEntryAgeMs(swarmEntry.created_at);
35884
- const ageThresholdMs = config3.auto_promote_days * 86400000;
35885
- if (ageMs >= ageThresholdMs) {
35886
- shouldPromote = true;
35887
- }
35888
- if (!shouldPromote) {
35898
+ if (!isHiveEligible(swarmEntry, config3.auto_promote_days)) {
35889
35899
  continue;
35890
35900
  }
35891
35901
  const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
@@ -37803,12 +37813,14 @@ async function handleCloseCommand(directory, args, options = {}) {
37803
37813
  if (planExists) {
37804
37814
  planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
37805
37815
  }
37806
- const config3 = KnowledgeConfigSchema.parse({});
37816
+ const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
37817
+ const config3 = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
37807
37818
  const projectName = planData.title ?? "Unknown Project";
37808
37819
  const closedPhases = [];
37809
37820
  const closedTasks = [];
37810
37821
  const warnings = [];
37811
37822
  let hivePromoted = 0;
37823
+ let hiveSkipped = 0;
37812
37824
  if (!planAlreadyDone) {
37813
37825
  for (const phase of inProgressPhases) {
37814
37826
  closedPhases.push(phase.id);
@@ -37931,23 +37943,35 @@ async function handleCloseCommand(directory, args, options = {}) {
37931
37943
  await fs7.unlink(lessonsFilePath).catch(() => {});
37932
37944
  }
37933
37945
  if (curationSucceeded) {
37934
- try {
37935
- const knowledgePath = resolveSwarmKnowledgePath(directory);
37936
- const entries = await readKnowledge(knowledgePath);
37937
- if (entries.length > 0) {
37938
- for (const entry of entries) {
37939
- try {
37940
- await promoteToHive(directory, entry.lesson, entry.category);
37941
- hivePromoted++;
37942
- } catch (promotionErr) {
37943
- const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
37944
- warnings.push(`Hive promotion skipped for lesson: ${msg}`);
37946
+ if (config3.hive_enabled === false) {} else {
37947
+ try {
37948
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
37949
+ const entries = await readKnowledge(knowledgePath);
37950
+ const autoPromoteDays = config3.auto_promote_days;
37951
+ if (entries.length > 0) {
37952
+ for (const entry of entries) {
37953
+ if (!isHiveEligible(entry, autoPromoteDays)) {
37954
+ hiveSkipped++;
37955
+ continue;
37956
+ }
37957
+ try {
37958
+ const result = await promoteToHive(directory, entry.lesson, entry.category);
37959
+ if (!result.includes("already exists")) {
37960
+ hivePromoted++;
37961
+ }
37962
+ } catch (promotionErr) {
37963
+ const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
37964
+ warnings.push(`Hive promotion skipped for lesson: ${msg}`);
37965
+ }
37966
+ }
37967
+ if (hiveSkipped > 0) {
37968
+ warnings.push(`${hiveSkipped} swarm knowledge entr${hiveSkipped === 1 ? "y" : "ies"} not eligible for hive promotion`);
37945
37969
  }
37946
37970
  }
37971
+ } catch (hiveErr) {
37972
+ const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
37973
+ warnings.push(`Hive promotion failed: ${msg}`);
37947
37974
  }
37948
- } catch (hiveErr) {
37949
- const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
37950
- warnings.push(`Hive promotion failed: ${msg}`);
37951
37975
  }
37952
37976
  }
37953
37977
  const fallbackKnowledgeCreated = curationResult?.stored ?? 0;
@@ -37964,8 +37988,8 @@ async function handleCloseCommand(directory, args, options = {}) {
37964
37988
  let skillReviewSummary = "";
37965
37989
  if (runSkillReview) {
37966
37990
  try {
37967
- const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
37968
- const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
37991
+ const { config: loadedConfig2 } = loadPluginConfigWithMeta(directory);
37992
+ const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig2.skill_improver ?? {});
37969
37993
  const skillReviewResult = await runAbortableSkillReview({
37970
37994
  directory,
37971
37995
  config: skillImproverConfig,
@@ -38330,7 +38354,6 @@ var init_close = __esm(() => {
38330
38354
  "handoff-prompt.md",
38331
38355
  "handoff-consumed.md",
38332
38356
  "escalation-report.md",
38333
- "knowledge.jsonl",
38334
38357
  "knowledge-rejected.jsonl",
38335
38358
  "repo-graph.json",
38336
38359
  "doc-manifest.json",
@@ -8,6 +8,18 @@ export interface HivePromotionSummary {
8
8
  advancements: number;
9
9
  total_hive_entries: number;
10
10
  }
11
+ /**
12
+ * Check whether a swarm knowledge entry is eligible for hive promotion.
13
+ * Three routes to eligibility:
14
+ * Route 1: hive_eligible flag + 3+ distinct phases
15
+ * Route 2: 'hive-fast-track' tag
16
+ * Route 3: age exceeds auto_promote_days threshold
17
+ *
18
+ * @param entry - The swarm knowledge entry to check
19
+ * @param autoPromoteDays - Number of days before age-based promotion kicks in
20
+ * @returns true if the entry is eligible for hive promotion
21
+ */
22
+ export declare function isHiveEligible(entry: SwarmKnowledgeEntry, autoPromoteDays: number): boolean;
11
23
  /**
12
24
  * Main promotion logic: checks swarm entries and promotes eligible ones to hive.
13
25
  * Also updates existing hive entries with new project confirmations.
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.24.0",
36
+ version: "7.24.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",
@@ -42694,6 +42694,20 @@ function normalizeEntry(raw) {
42694
42694
  ro.failed_after_shown_count = typeof ro.failed_after_count === "number" ? ro.failed_after_count : 0;
42695
42695
  }
42696
42696
  }
42697
+ try {
42698
+ if (typeof obj.encounter_score !== "number" || Number.isNaN(obj.encounter_score)) {
42699
+ obj.encounter_score = 0;
42700
+ }
42701
+ } catch {
42702
+ try {
42703
+ Object.defineProperty(obj, "encounter_score", {
42704
+ value: 0,
42705
+ writable: true,
42706
+ configurable: true,
42707
+ enumerable: true
42708
+ });
42709
+ } catch {}
42710
+ }
42697
42711
  const arrayFields = [
42698
42712
  "triggers",
42699
42713
  "required_actions",
@@ -44618,12 +44632,26 @@ import path19 from "node:path";
44618
44632
  function isAlreadyInHive(entry, hiveEntries, threshold) {
44619
44633
  return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
44620
44634
  }
44621
- function countDistinctPhases(confirmedBy) {
44635
+ function isHiveEligible(entry, autoPromoteDays) {
44622
44636
  const phaseNumbers = new Set;
44623
- for (const record3 of confirmedBy) {
44624
- phaseNumbers.add(record3.phase_number);
44637
+ for (const record3 of entry.confirmed_by ?? []) {
44638
+ if (record3 && typeof record3.phase_number === "number") {
44639
+ phaseNumbers.add(record3.phase_number);
44640
+ }
44625
44641
  }
44626
- return phaseNumbers.size;
44642
+ if (entry.hive_eligible === true && phaseNumbers.size >= 3) {
44643
+ return true;
44644
+ }
44645
+ if ((entry.tags ?? []).includes("hive-fast-track")) {
44646
+ return true;
44647
+ }
44648
+ const createdMs = Date.parse(entry.created_at);
44649
+ const ageMs = Number.isFinite(createdMs) ? Date.now() - createdMs : 0;
44650
+ const ageThresholdMs = autoPromoteDays * 86400000;
44651
+ if (ageMs >= ageThresholdMs) {
44652
+ return true;
44653
+ }
44654
+ return false;
44627
44655
  }
44628
44656
  function countDistinctProjects(confirmedBy) {
44629
44657
  const projectNames = new Set;
@@ -44641,12 +44669,6 @@ function calculateEncounterScore(currentScore, isSameProject, config3) {
44641
44669
  const newScore = currentScore + increment;
44642
44670
  return Math.min(Math.max(newScore, config3.min_encounter_score), config3.max_encounter_score);
44643
44671
  }
44644
- function getEntryAgeMs(createdAt) {
44645
- const createdTime = new Date(createdAt).getTime();
44646
- if (Number.isNaN(createdTime))
44647
- return 0;
44648
- return Date.now() - createdTime;
44649
- }
44650
44672
  async function checkHivePromotions(swarmEntries, config3) {
44651
44673
  let newPromotions = 0;
44652
44674
  let encountersIncremented = 0;
@@ -44665,19 +44687,7 @@ async function checkHivePromotions(swarmEntries, config3) {
44665
44687
  if (isAlreadyInHive(swarmEntry, hiveEntries, config3.dedup_threshold)) {
44666
44688
  continue;
44667
44689
  }
44668
- let shouldPromote = false;
44669
- if (swarmEntry.hive_eligible === true && countDistinctPhases(swarmEntry.confirmed_by) >= 3) {
44670
- shouldPromote = true;
44671
- }
44672
- if (swarmEntry.tags.includes("hive-fast-track")) {
44673
- shouldPromote = true;
44674
- }
44675
- const ageMs = getEntryAgeMs(swarmEntry.created_at);
44676
- const ageThresholdMs = config3.auto_promote_days * 86400000;
44677
- if (ageMs >= ageThresholdMs) {
44678
- shouldPromote = true;
44679
- }
44680
- if (!shouldPromote) {
44690
+ if (!isHiveEligible(swarmEntry, config3.auto_promote_days)) {
44681
44691
  continue;
44682
44692
  }
44683
44693
  const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
@@ -46554,12 +46564,14 @@ async function handleCloseCommand(directory, args2, options = {}) {
46554
46564
  if (planExists) {
46555
46565
  planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
46556
46566
  }
46557
- const config3 = KnowledgeConfigSchema.parse({});
46567
+ const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
46568
+ const config3 = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
46558
46569
  const projectName = planData.title ?? "Unknown Project";
46559
46570
  const closedPhases = [];
46560
46571
  const closedTasks = [];
46561
46572
  const warnings = [];
46562
46573
  let hivePromoted = 0;
46574
+ let hiveSkipped = 0;
46563
46575
  if (!planAlreadyDone) {
46564
46576
  for (const phase of inProgressPhases) {
46565
46577
  closedPhases.push(phase.id);
@@ -46682,23 +46694,35 @@ async function handleCloseCommand(directory, args2, options = {}) {
46682
46694
  await fs13.unlink(lessonsFilePath).catch(() => {});
46683
46695
  }
46684
46696
  if (curationSucceeded) {
46685
- try {
46686
- const knowledgePath = resolveSwarmKnowledgePath(directory);
46687
- const entries = await readKnowledge(knowledgePath);
46688
- if (entries.length > 0) {
46689
- for (const entry of entries) {
46690
- try {
46691
- await promoteToHive(directory, entry.lesson, entry.category);
46692
- hivePromoted++;
46693
- } catch (promotionErr) {
46694
- const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
46695
- warnings.push(`Hive promotion skipped for lesson: ${msg}`);
46697
+ if (config3.hive_enabled === false) {} else {
46698
+ try {
46699
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
46700
+ const entries = await readKnowledge(knowledgePath);
46701
+ const autoPromoteDays = config3.auto_promote_days;
46702
+ if (entries.length > 0) {
46703
+ for (const entry of entries) {
46704
+ if (!isHiveEligible(entry, autoPromoteDays)) {
46705
+ hiveSkipped++;
46706
+ continue;
46707
+ }
46708
+ try {
46709
+ const result = await promoteToHive(directory, entry.lesson, entry.category);
46710
+ if (!result.includes("already exists")) {
46711
+ hivePromoted++;
46712
+ }
46713
+ } catch (promotionErr) {
46714
+ const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
46715
+ warnings.push(`Hive promotion skipped for lesson: ${msg}`);
46716
+ }
46717
+ }
46718
+ if (hiveSkipped > 0) {
46719
+ warnings.push(`${hiveSkipped} swarm knowledge entr${hiveSkipped === 1 ? "y" : "ies"} not eligible for hive promotion`);
46696
46720
  }
46697
46721
  }
46722
+ } catch (hiveErr) {
46723
+ const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
46724
+ warnings.push(`Hive promotion failed: ${msg}`);
46698
46725
  }
46699
- } catch (hiveErr) {
46700
- const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
46701
- warnings.push(`Hive promotion failed: ${msg}`);
46702
46726
  }
46703
46727
  }
46704
46728
  const fallbackKnowledgeCreated = curationResult?.stored ?? 0;
@@ -46715,8 +46739,8 @@ async function handleCloseCommand(directory, args2, options = {}) {
46715
46739
  let skillReviewSummary = "";
46716
46740
  if (runSkillReview) {
46717
46741
  try {
46718
- const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
46719
- const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
46742
+ const { config: loadedConfig2 } = loadPluginConfigWithMeta(directory);
46743
+ const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig2.skill_improver ?? {});
46720
46744
  const skillReviewResult = await runAbortableSkillReview({
46721
46745
  directory,
46722
46746
  config: skillImproverConfig,
@@ -47081,7 +47105,6 @@ var init_close = __esm(() => {
47081
47105
  "handoff-prompt.md",
47082
47106
  "handoff-consumed.md",
47083
47107
  "escalation-report.md",
47084
- "knowledge.jsonl",
47085
47108
  "knowledge-rejected.jsonl",
47086
47109
  "repo-graph.json",
47087
47110
  "doc-manifest.json",
@@ -90429,7 +90452,7 @@ function formatHiveEntry(entry) {
90429
90452
  lines.push(` Category: ${entry.category}`);
90430
90453
  lines.push(` Status: ${entry.status}`);
90431
90454
  lines.push(` Confidence: ${entry.confidence.toFixed(2)}`);
90432
- lines.push(` Encounter Score: ${entry.encounter_score.toFixed(2)}`);
90455
+ lines.push(` Encounter Score: ${entry.encounter_score?.toFixed(2) ?? "N/A"}`);
90433
90456
  lines.push(` Source Project: ${entry.source_project}`);
90434
90457
  lines.push(` Confirmed by: ${entry.confirmed_by.length} project(s)`);
90435
90458
  return lines.join(`
@@ -2,4 +2,10 @@
2
2
  * Provides filtered, formatted text output for knowledge retrieval.
3
3
  */
4
4
  import type { tool } from '@opencode-ai/plugin';
5
+ import type { HiveKnowledgeEntry } from '../hooks/knowledge-types.js';
6
+ declare function formatHiveEntry(entry: HiveKnowledgeEntry): string;
5
7
  export declare const knowledge_query: ReturnType<typeof tool>;
8
+ export declare const _test_exports: {
9
+ formatHiveEntry: typeof formatHiveEntry;
10
+ };
11
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.24.0",
3
+ "version": "7.24.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",