opencode-swarm 6.86.11 → 6.86.12

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
@@ -18580,7 +18580,7 @@ import * as path33 from "path";
18580
18580
  // package.json
18581
18581
  var package_default = {
18582
18582
  name: "opencode-swarm",
18583
- version: "6.86.11",
18583
+ version: "6.86.12",
18584
18584
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
18585
18585
  main: "dist/index.js",
18586
18586
  types: "dist/index.d.ts",
@@ -39480,6 +39480,9 @@ async function handleHistoryCommand(directory, _args) {
39480
39480
  const historyData = await getHistoryData(directory);
39481
39481
  return formatHistoryMarkdown(historyData);
39482
39482
  }
39483
+ // src/commands/knowledge.ts
39484
+ import { join as join21 } from "path";
39485
+
39483
39486
  // src/hooks/knowledge-migrator.ts
39484
39487
  init_logger();
39485
39488
  import { randomUUID as randomUUID2 } from "crypto";
@@ -39710,34 +39713,65 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
39710
39713
  }
39711
39714
 
39712
39715
  // src/commands/knowledge.ts
39716
+ function resolveEntryByPrefix(entries, inputId) {
39717
+ const exact = entries.find((e) => e.id === inputId);
39718
+ if (exact)
39719
+ return { entry: exact };
39720
+ const matches = entries.filter((e) => e.id.startsWith(inputId));
39721
+ if (matches.length === 0) {
39722
+ return { error: `No entry found matching '${inputId}'.` };
39723
+ }
39724
+ if (matches.length === 1) {
39725
+ return { entry: matches[0] };
39726
+ }
39727
+ const candidates = matches.map((e) => e.id).join(`
39728
+ `);
39729
+ return {
39730
+ error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
39731
+ ${candidates}`
39732
+ };
39733
+ }
39713
39734
  async function handleKnowledgeQuarantineCommand(directory, args) {
39714
- const entryId = args[0];
39715
- if (!entryId) {
39735
+ const inputId = args[0];
39736
+ if (!inputId) {
39716
39737
  return "Usage: /swarm knowledge quarantine <id> [reason]";
39717
39738
  }
39718
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
39739
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
39719
39740
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
39720
39741
  }
39721
39742
  const reason = args.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
39722
39743
  try {
39723
- await quarantineEntry(directory, entryId, reason, "user");
39724
- return `\u2705 Entry ${entryId} quarantined successfully.`;
39744
+ const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
39745
+ const resolved = resolveEntryByPrefix(entries, inputId);
39746
+ if ("error" in resolved) {
39747
+ return `\u274C ${resolved.error}`;
39748
+ }
39749
+ const fullId = resolved.entry.id;
39750
+ await quarantineEntry(directory, fullId, reason, "user");
39751
+ return `\u2705 Entry ${fullId} quarantined successfully.`;
39725
39752
  } catch (error93) {
39726
39753
  console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
39727
39754
  return `\u274C Failed to quarantine entry. Check the entry ID and try again.`;
39728
39755
  }
39729
39756
  }
39730
39757
  async function handleKnowledgeRestoreCommand(directory, args) {
39731
- const entryId = args[0];
39732
- if (!entryId) {
39758
+ const inputId = args[0];
39759
+ if (!inputId) {
39733
39760
  return "Usage: /swarm knowledge restore <id>";
39734
39761
  }
39735
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
39762
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
39736
39763
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
39737
39764
  }
39738
39765
  try {
39739
- await restoreEntry(directory, entryId);
39740
- return `\u2705 Entry ${entryId} restored successfully.`;
39766
+ const quarantinePath = join21(directory, ".swarm", "knowledge-quarantined.jsonl");
39767
+ const entries = await readKnowledge(quarantinePath);
39768
+ const resolved = resolveEntryByPrefix(entries, inputId);
39769
+ if ("error" in resolved) {
39770
+ return `\u274C ${resolved.error}`;
39771
+ }
39772
+ const fullId = resolved.entry.id;
39773
+ await restoreEntry(directory, fullId);
39774
+ return `\u2705 Entry ${fullId} restored successfully.`;
39741
39775
  } catch (error93) {
39742
39776
  console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
39743
39777
  return `\u274C Failed to restore entry. Check the entry ID and try again.`;
@@ -39775,16 +39809,16 @@ async function handleKnowledgeListCommand(directory, _args) {
39775
39809
  const lines = [
39776
39810
  `## Knowledge Entries (${entries.length} total)`,
39777
39811
  "",
39778
- "| ID | Category | Confidence | Lesson (truncated) |",
39779
- "|------|----------|------------|---------------------|"
39812
+ "| ID (prefix) | Category | Confidence | Lesson (truncated) |",
39813
+ "|--------------|----------|------------|---------------------|"
39780
39814
  ];
39781
39815
  for (const entry of entries) {
39782
39816
  const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
39783
39817
  const confidencePct = Math.round(entry.confidence * 100);
39784
- lines.push(`| ${entry.id.slice(0, 8)}... | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
39818
+ lines.push(`| ${entry.id.slice(0, 12)}\u2026 | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
39785
39819
  }
39786
39820
  lines.push("");
39787
- lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
39821
+ lines.push("Use `/swarm knowledge quarantine <id-prefix>` to hide an entry. Prefix matching is supported \u2014 the 12-character prefix shown is unique in most stores.");
39788
39822
  return lines.join(`
39789
39823
  `);
39790
39824
  } catch (error93) {
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * Handles /swarm knowledge quarantine <id> [reason] command.
3
3
  * Moves a knowledge entry to quarantine with optional reason.
4
+ * Accepts a full ID or a unique prefix.
4
5
  */
5
6
  export declare function handleKnowledgeQuarantineCommand(directory: string, args: string[]): Promise<string>;
6
7
  /**
7
8
  * Handles /swarm knowledge restore <id> command.
8
9
  * Restores a quarantined knowledge entry.
10
+ * Accepts a full ID or a unique prefix.
9
11
  */
10
12
  export declare function handleKnowledgeRestoreCommand(directory: string, args: string[]): Promise<string>;
11
13
  /**
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: "6.86.11",
36
+ version: "6.86.12",
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",
@@ -48396,34 +48396,66 @@ var init_knowledge_migrator = __esm(() => {
48396
48396
  });
48397
48397
 
48398
48398
  // src/commands/knowledge.ts
48399
+ import { join as join28 } from "node:path";
48400
+ function resolveEntryByPrefix(entries, inputId) {
48401
+ const exact = entries.find((e) => e.id === inputId);
48402
+ if (exact)
48403
+ return { entry: exact };
48404
+ const matches = entries.filter((e) => e.id.startsWith(inputId));
48405
+ if (matches.length === 0) {
48406
+ return { error: `No entry found matching '${inputId}'.` };
48407
+ }
48408
+ if (matches.length === 1) {
48409
+ return { entry: matches[0] };
48410
+ }
48411
+ const candidates = matches.map((e) => e.id).join(`
48412
+ `);
48413
+ return {
48414
+ error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
48415
+ ${candidates}`
48416
+ };
48417
+ }
48399
48418
  async function handleKnowledgeQuarantineCommand(directory, args2) {
48400
- const entryId = args2[0];
48401
- if (!entryId) {
48419
+ const inputId = args2[0];
48420
+ if (!inputId) {
48402
48421
  return "Usage: /swarm knowledge quarantine <id> [reason]";
48403
48422
  }
48404
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
48423
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
48405
48424
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
48406
48425
  }
48407
48426
  const reason = args2.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
48408
48427
  try {
48409
- await quarantineEntry(directory, entryId, reason, "user");
48410
- return `✅ Entry ${entryId} quarantined successfully.`;
48428
+ const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
48429
+ const resolved = resolveEntryByPrefix(entries, inputId);
48430
+ if ("error" in resolved) {
48431
+ return `❌ ${resolved.error}`;
48432
+ }
48433
+ const fullId = resolved.entry.id;
48434
+ await quarantineEntry(directory, fullId, reason, "user");
48435
+ return `✅ Entry ${fullId} quarantined successfully.`;
48411
48436
  } catch (error93) {
48412
48437
  console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
48413
48438
  return `❌ Failed to quarantine entry. Check the entry ID and try again.`;
48414
48439
  }
48415
48440
  }
48416
48441
  async function handleKnowledgeRestoreCommand(directory, args2) {
48417
- const entryId = args2[0];
48418
- if (!entryId) {
48442
+ const inputId = args2[0];
48443
+ if (!inputId) {
48419
48444
  return "Usage: /swarm knowledge restore <id>";
48420
48445
  }
48421
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
48446
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
48422
48447
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
48423
48448
  }
48424
48449
  try {
48425
- await restoreEntry(directory, entryId);
48426
- return `✅ Entry ${entryId} restored successfully.`;
48450
+ const quarantinePath = join28(directory, ".swarm", "knowledge-quarantined.jsonl");
48451
+ const entries = await readKnowledge(quarantinePath);
48452
+ const resolved = resolveEntryByPrefix(entries, inputId);
48453
+ if ("error" in resolved) {
48454
+ return `❌ ${resolved.error}`;
48455
+ }
48456
+ const fullId = resolved.entry.id;
48457
+ await restoreEntry(directory, fullId);
48458
+ return `✅ Entry ${fullId} restored successfully.`;
48427
48459
  } catch (error93) {
48428
48460
  console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
48429
48461
  return `❌ Failed to restore entry. Check the entry ID and try again.`;
@@ -48461,16 +48493,16 @@ async function handleKnowledgeListCommand(directory, _args) {
48461
48493
  const lines = [
48462
48494
  `## Knowledge Entries (${entries.length} total)`,
48463
48495
  "",
48464
- "| ID | Category | Confidence | Lesson (truncated) |",
48465
- "|------|----------|------------|---------------------|"
48496
+ "| ID (prefix) | Category | Confidence | Lesson (truncated) |",
48497
+ "|--------------|----------|------------|---------------------|"
48466
48498
  ];
48467
48499
  for (const entry of entries) {
48468
48500
  const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
48469
48501
  const confidencePct = Math.round(entry.confidence * 100);
48470
- lines.push(`| ${entry.id.slice(0, 8)}... | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
48502
+ lines.push(`| ${entry.id.slice(0, 12)} | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
48471
48503
  }
48472
48504
  lines.push("");
48473
- lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
48505
+ lines.push("Use `/swarm knowledge quarantine <id-prefix>` to hide an entry. Prefix matching is supported — the 12-character prefix shown is unique in most stores.");
48474
48506
  return lines.join(`
48475
48507
  `);
48476
48508
  } catch (error93) {
@@ -63841,7 +63873,7 @@ ${content.substring(endIndex + 1)}`;
63841
63873
  init_manager();
63842
63874
  init_utils2();
63843
63875
  import * as fs31 from "node:fs";
63844
- import { join as join41 } from "node:path";
63876
+ import { join as join42 } from "node:path";
63845
63877
  function createCompactionCustomizerHook(config3, directory) {
63846
63878
  const enabled = config3.hooks?.compaction !== false;
63847
63879
  if (!enabled) {
@@ -63886,7 +63918,7 @@ function createCompactionCustomizerHook(config3, directory) {
63886
63918
  }
63887
63919
  }
63888
63920
  try {
63889
- const summariesDir = join41(directory, ".swarm", "summaries");
63921
+ const summariesDir = join42(directory, ".swarm", "summaries");
63890
63922
  const files = await fs31.promises.readdir(summariesDir);
63891
63923
  if (files.length > 0) {
63892
63924
  const count = files.length;
@@ -74619,7 +74651,7 @@ import {
74619
74651
  readFileSync as readFileSync36,
74620
74652
  writeFileSync as writeFileSync11
74621
74653
  } from "node:fs";
74622
- import { join as join65 } from "node:path";
74654
+ import { join as join66 } from "node:path";
74623
74655
  var EVIDENCE_DIR2 = ".swarm/evidence";
74624
74656
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
74625
74657
  var COUNCIL_GATE_NAME = "council";
@@ -74653,9 +74685,9 @@ function writeCouncilEvidence(workingDir, synthesis) {
74653
74685
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
74654
74686
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
74655
74687
  }
74656
- const dir = join65(workingDir, EVIDENCE_DIR2);
74688
+ const dir = join66(workingDir, EVIDENCE_DIR2);
74657
74689
  mkdirSync18(dir, { recursive: true });
74658
- const filePath = join65(dir, `${synthesis.taskId}.json`);
74690
+ const filePath = join66(dir, `${synthesis.taskId}.json`);
74659
74691
  const existingRoot = Object.create(null);
74660
74692
  if (existsSync37(filePath)) {
74661
74693
  try {
@@ -74689,7 +74721,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
74689
74721
  updated.required_gates = [];
74690
74722
  writeFileSync11(filePath, JSON.stringify(updated, null, 2));
74691
74723
  try {
74692
- const councilDir = join65(workingDir, ".swarm", "council");
74724
+ const councilDir = join66(workingDir, ".swarm", "council");
74693
74725
  mkdirSync18(councilDir, { recursive: true });
74694
74726
  const auditLine = JSON.stringify({
74695
74727
  round: synthesis.roundNumber,
@@ -74697,7 +74729,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
74697
74729
  timestamp: synthesis.timestamp,
74698
74730
  vetoedBy: synthesis.vetoedBy
74699
74731
  });
74700
- appendFileSync6(join65(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
74732
+ appendFileSync6(join66(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
74701
74733
  `);
74702
74734
  } catch (auditError) {
74703
74735
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -74830,20 +74862,20 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
74830
74862
 
74831
74863
  // src/council/criteria-store.ts
74832
74864
  import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "node:fs";
74833
- import { join as join66 } from "node:path";
74865
+ import { join as join67 } from "node:path";
74834
74866
  var COUNCIL_DIR = ".swarm/council";
74835
74867
  function writeCriteria(workingDir, taskId, criteria) {
74836
- const dir = join66(workingDir, COUNCIL_DIR);
74868
+ const dir = join67(workingDir, COUNCIL_DIR);
74837
74869
  mkdirSync19(dir, { recursive: true });
74838
74870
  const payload = {
74839
74871
  taskId,
74840
74872
  criteria,
74841
74873
  declaredAt: new Date().toISOString()
74842
74874
  };
74843
- writeFileSync12(join66(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
74875
+ writeFileSync12(join67(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
74844
74876
  }
74845
74877
  function readCriteria(workingDir, taskId) {
74846
- const filePath = join66(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
74878
+ const filePath = join67(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
74847
74879
  if (!existsSync38(filePath))
74848
74880
  return null;
74849
74881
  try {
@@ -77388,6 +77420,7 @@ var VALID_CATEGORIES2 = [
77388
77420
  "debugging",
77389
77421
  "performance",
77390
77422
  "integration",
77423
+ "todo",
77391
77424
  "other"
77392
77425
  ];
77393
77426
  var knowledge_add = createSwarmTool({
@@ -77532,6 +77565,7 @@ var VALID_CATEGORIES3 = [
77532
77565
  "debugging",
77533
77566
  "performance",
77534
77567
  "integration",
77568
+ "todo",
77535
77569
  "other"
77536
77570
  ];
77537
77571
  var VALID_STATUSES = ["candidate", "established", "promoted"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.86.11",
3
+ "version": "6.86.12",
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",