opencode-swarm 6.86.11 → 6.86.13

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.13",
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",
@@ -19472,7 +19472,8 @@ var PlanCursorConfigSchema = exports_external.object({
19472
19472
  });
19473
19473
  var CheckpointConfigSchema = exports_external.object({
19474
19474
  enabled: exports_external.boolean().default(true),
19475
- auto_checkpoint_threshold: exports_external.number().int().min(1).max(20).default(3)
19475
+ auto_checkpoint_threshold: exports_external.number().int().min(1).max(20).default(3),
19476
+ allow_empty_commits: exports_external.boolean().default(false)
19476
19477
  }).strict();
19477
19478
  var AutomationModeSchema = exports_external.enum(["manual", "hybrid", "auto"]);
19478
19479
  var AutomationCapabilitiesSchema = exports_external.object({
@@ -19683,7 +19684,7 @@ var PluginConfigSchema = exports_external.object({
19683
19684
  council: CouncilConfigSchema.optional(),
19684
19685
  parallelization: ParallelizationConfigSchema.optional(),
19685
19686
  turbo_mode: exports_external.boolean().default(false).optional(),
19686
- quiet: exports_external.boolean().default(false).optional(),
19687
+ quiet: exports_external.boolean().default(true).optional(),
19687
19688
  version_check: exports_external.boolean().default(true).optional(),
19688
19689
  full_auto: exports_external.object({
19689
19690
  enabled: exports_external.boolean().default(false),
@@ -33500,9 +33501,11 @@ function isGitRepo() {
33500
33501
  function handleSave(label, directory) {
33501
33502
  try {
33502
33503
  let maxCheckpoints = 20;
33504
+ let allowEmptyCommits = false;
33503
33505
  try {
33504
33506
  const { config: config3 } = loadPluginConfigWithMeta(directory);
33505
33507
  maxCheckpoints = config3.checkpoint?.auto_checkpoint_threshold ?? maxCheckpoints;
33508
+ allowEmptyCommits = config3.checkpoint?.allow_empty_commits === true;
33506
33509
  } catch {}
33507
33510
  const log2 = readCheckpointLog(directory);
33508
33511
  const existingCheckpoint = log2.checkpoints.find((c) => c.label === label);
@@ -33513,9 +33516,21 @@ function handleSave(label, directory) {
33513
33516
  error: `duplicate label: "${label}" already exists. Use a different label or delete the existing checkpoint first.`
33514
33517
  }, null, 2);
33515
33518
  }
33516
- const _sha = getCurrentSha();
33517
33519
  const timestamp = new Date().toISOString();
33518
- gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
33520
+ gitExec(["add", "--all", "--", ":!.swarm/"]);
33521
+ const hasStagedChanges = (() => {
33522
+ try {
33523
+ gitExec(["diff", "--cached", "--quiet"]);
33524
+ return false;
33525
+ } catch {
33526
+ return true;
33527
+ }
33528
+ })();
33529
+ if (hasStagedChanges) {
33530
+ gitExec(["commit", "-m", `checkpoint: ${label}`]);
33531
+ } else if (allowEmptyCommits) {
33532
+ gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
33533
+ }
33519
33534
  const newSha = getCurrentSha();
33520
33535
  log2.checkpoints.push({
33521
33536
  label,
@@ -33594,7 +33609,7 @@ function handleDelete(label, directory) {
33594
33609
  action: "delete",
33595
33610
  success: true,
33596
33611
  label,
33597
- message: `Checkpoint deleted: "${label}" (git commit preserved)`
33612
+ message: `Checkpoint deleted: "${label}"`
33598
33613
  }, null, 2);
33599
33614
  } catch (e) {
33600
33615
  const errorMessage = e instanceof Error ? `delete failed: ${e.message}` : "delete failed: unknown error";
@@ -39480,6 +39495,9 @@ async function handleHistoryCommand(directory, _args) {
39480
39495
  const historyData = await getHistoryData(directory);
39481
39496
  return formatHistoryMarkdown(historyData);
39482
39497
  }
39498
+ // src/commands/knowledge.ts
39499
+ import { join as join21 } from "path";
39500
+
39483
39501
  // src/hooks/knowledge-migrator.ts
39484
39502
  init_logger();
39485
39503
  import { randomUUID as randomUUID2 } from "crypto";
@@ -39710,34 +39728,65 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
39710
39728
  }
39711
39729
 
39712
39730
  // src/commands/knowledge.ts
39731
+ function resolveEntryByPrefix(entries, inputId) {
39732
+ const exact = entries.find((e) => e.id === inputId);
39733
+ if (exact)
39734
+ return { entry: exact };
39735
+ const matches = entries.filter((e) => e.id.startsWith(inputId));
39736
+ if (matches.length === 0) {
39737
+ return { error: `No entry found matching '${inputId}'.` };
39738
+ }
39739
+ if (matches.length === 1) {
39740
+ return { entry: matches[0] };
39741
+ }
39742
+ const candidates = matches.map((e) => e.id).join(`
39743
+ `);
39744
+ return {
39745
+ error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
39746
+ ${candidates}`
39747
+ };
39748
+ }
39713
39749
  async function handleKnowledgeQuarantineCommand(directory, args) {
39714
- const entryId = args[0];
39715
- if (!entryId) {
39750
+ const inputId = args[0];
39751
+ if (!inputId) {
39716
39752
  return "Usage: /swarm knowledge quarantine <id> [reason]";
39717
39753
  }
39718
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
39754
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
39719
39755
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
39720
39756
  }
39721
39757
  const reason = args.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
39722
39758
  try {
39723
- await quarantineEntry(directory, entryId, reason, "user");
39724
- return `\u2705 Entry ${entryId} quarantined successfully.`;
39759
+ const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
39760
+ const resolved = resolveEntryByPrefix(entries, inputId);
39761
+ if ("error" in resolved) {
39762
+ return `\u274C ${resolved.error}`;
39763
+ }
39764
+ const fullId = resolved.entry.id;
39765
+ await quarantineEntry(directory, fullId, reason, "user");
39766
+ return `\u2705 Entry ${fullId} quarantined successfully.`;
39725
39767
  } catch (error93) {
39726
39768
  console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
39727
39769
  return `\u274C Failed to quarantine entry. Check the entry ID and try again.`;
39728
39770
  }
39729
39771
  }
39730
39772
  async function handleKnowledgeRestoreCommand(directory, args) {
39731
- const entryId = args[0];
39732
- if (!entryId) {
39773
+ const inputId = args[0];
39774
+ if (!inputId) {
39733
39775
  return "Usage: /swarm knowledge restore <id>";
39734
39776
  }
39735
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
39777
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
39736
39778
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
39737
39779
  }
39738
39780
  try {
39739
- await restoreEntry(directory, entryId);
39740
- return `\u2705 Entry ${entryId} restored successfully.`;
39781
+ const quarantinePath = join21(directory, ".swarm", "knowledge-quarantined.jsonl");
39782
+ const entries = await readKnowledge(quarantinePath);
39783
+ const resolved = resolveEntryByPrefix(entries, inputId);
39784
+ if ("error" in resolved) {
39785
+ return `\u274C ${resolved.error}`;
39786
+ }
39787
+ const fullId = resolved.entry.id;
39788
+ await restoreEntry(directory, fullId);
39789
+ return `\u2705 Entry ${fullId} restored successfully.`;
39741
39790
  } catch (error93) {
39742
39791
  console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
39743
39792
  return `\u274C Failed to restore entry. Check the entry ID and try again.`;
@@ -39775,16 +39824,16 @@ async function handleKnowledgeListCommand(directory, _args) {
39775
39824
  const lines = [
39776
39825
  `## Knowledge Entries (${entries.length} total)`,
39777
39826
  "",
39778
- "| ID | Category | Confidence | Lesson (truncated) |",
39779
- "|------|----------|------------|---------------------|"
39827
+ "| ID (prefix) | Category | Confidence | Lesson (truncated) |",
39828
+ "|--------------|----------|------------|---------------------|"
39780
39829
  ];
39781
39830
  for (const entry of entries) {
39782
39831
  const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
39783
39832
  const confidencePct = Math.round(entry.confidence * 100);
39784
- lines.push(`| ${entry.id.slice(0, 8)}... | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
39833
+ lines.push(`| ${entry.id.slice(0, 12)}\u2026 | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
39785
39834
  }
39786
39835
  lines.push("");
39787
- lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
39836
+ 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
39837
  return lines.join(`
39789
39838
  `);
39790
39839
  } 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
  /**
@@ -380,6 +380,7 @@ export type PlanCursorConfig = z.infer<typeof PlanCursorConfigSchema>;
380
380
  export declare const CheckpointConfigSchema: z.ZodObject<{
381
381
  enabled: z.ZodDefault<z.ZodBoolean>;
382
382
  auto_checkpoint_threshold: z.ZodDefault<z.ZodNumber>;
383
+ allow_empty_commits: z.ZodDefault<z.ZodBoolean>;
383
384
  }, z.core.$strict>;
384
385
  export type CheckpointConfig = z.infer<typeof CheckpointConfigSchema>;
385
386
  export declare const AutomationModeSchema: z.ZodEnum<{
@@ -885,6 +886,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
885
886
  checkpoint: z.ZodOptional<z.ZodObject<{
886
887
  enabled: z.ZodDefault<z.ZodBoolean>;
887
888
  auto_checkpoint_threshold: z.ZodDefault<z.ZodNumber>;
889
+ allow_empty_commits: z.ZodDefault<z.ZodBoolean>;
888
890
  }, z.core.$strict>>;
889
891
  automation: z.ZodOptional<z.ZodType<{
890
892
  mode: "auto" | "manual" | "hybrid";
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.13",
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",
@@ -15179,7 +15179,8 @@ var init_schema = __esm(() => {
15179
15179
  });
15180
15180
  CheckpointConfigSchema = exports_external.object({
15181
15181
  enabled: exports_external.boolean().default(true),
15182
- auto_checkpoint_threshold: exports_external.number().int().min(1).max(20).default(3)
15182
+ auto_checkpoint_threshold: exports_external.number().int().min(1).max(20).default(3),
15183
+ allow_empty_commits: exports_external.boolean().default(false)
15183
15184
  }).strict();
15184
15185
  AutomationModeSchema = exports_external.enum(["manual", "hybrid", "auto"]);
15185
15186
  AutomationCapabilitiesSchema = exports_external.object({
@@ -15390,7 +15391,7 @@ var init_schema = __esm(() => {
15390
15391
  council: CouncilConfigSchema.optional(),
15391
15392
  parallelization: ParallelizationConfigSchema.optional(),
15392
15393
  turbo_mode: exports_external.boolean().default(false).optional(),
15393
- quiet: exports_external.boolean().default(false).optional(),
15394
+ quiet: exports_external.boolean().default(true).optional(),
15394
15395
  version_check: exports_external.boolean().default(true).optional(),
15395
15396
  full_auto: exports_external.object({
15396
15397
  enabled: exports_external.boolean().default(false),
@@ -39551,9 +39552,11 @@ function isGitRepo() {
39551
39552
  function handleSave(label, directory) {
39552
39553
  try {
39553
39554
  let maxCheckpoints = 20;
39555
+ let allowEmptyCommits = false;
39554
39556
  try {
39555
39557
  const { config: config3 } = loadPluginConfigWithMeta(directory);
39556
39558
  maxCheckpoints = config3.checkpoint?.auto_checkpoint_threshold ?? maxCheckpoints;
39559
+ allowEmptyCommits = config3.checkpoint?.allow_empty_commits === true;
39557
39560
  } catch {}
39558
39561
  const log2 = readCheckpointLog(directory);
39559
39562
  const existingCheckpoint = log2.checkpoints.find((c) => c.label === label);
@@ -39564,9 +39567,21 @@ function handleSave(label, directory) {
39564
39567
  error: `duplicate label: "${label}" already exists. Use a different label or delete the existing checkpoint first.`
39565
39568
  }, null, 2);
39566
39569
  }
39567
- const _sha = getCurrentSha();
39568
39570
  const timestamp = new Date().toISOString();
39569
- gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
39571
+ gitExec(["add", "--all", "--", ":!.swarm/"]);
39572
+ const hasStagedChanges = (() => {
39573
+ try {
39574
+ gitExec(["diff", "--cached", "--quiet"]);
39575
+ return false;
39576
+ } catch {
39577
+ return true;
39578
+ }
39579
+ })();
39580
+ if (hasStagedChanges) {
39581
+ gitExec(["commit", "-m", `checkpoint: ${label}`]);
39582
+ } else if (allowEmptyCommits) {
39583
+ gitExec(["commit", "--allow-empty", "-m", `checkpoint: ${label}`]);
39584
+ }
39570
39585
  const newSha = getCurrentSha();
39571
39586
  log2.checkpoints.push({
39572
39587
  label,
@@ -39645,7 +39660,7 @@ function handleDelete(label, directory) {
39645
39660
  action: "delete",
39646
39661
  success: true,
39647
39662
  label,
39648
- message: `Checkpoint deleted: "${label}" (git commit preserved)`
39663
+ message: `Checkpoint deleted: "${label}"`
39649
39664
  }, null, 2);
39650
39665
  } catch (e) {
39651
39666
  const errorMessage = e instanceof Error ? `delete failed: ${e.message}` : "delete failed: unknown error";
@@ -48396,34 +48411,66 @@ var init_knowledge_migrator = __esm(() => {
48396
48411
  });
48397
48412
 
48398
48413
  // src/commands/knowledge.ts
48414
+ import { join as join28 } from "node:path";
48415
+ function resolveEntryByPrefix(entries, inputId) {
48416
+ const exact = entries.find((e) => e.id === inputId);
48417
+ if (exact)
48418
+ return { entry: exact };
48419
+ const matches = entries.filter((e) => e.id.startsWith(inputId));
48420
+ if (matches.length === 0) {
48421
+ return { error: `No entry found matching '${inputId}'.` };
48422
+ }
48423
+ if (matches.length === 1) {
48424
+ return { entry: matches[0] };
48425
+ }
48426
+ const candidates = matches.map((e) => e.id).join(`
48427
+ `);
48428
+ return {
48429
+ error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
48430
+ ${candidates}`
48431
+ };
48432
+ }
48399
48433
  async function handleKnowledgeQuarantineCommand(directory, args2) {
48400
- const entryId = args2[0];
48401
- if (!entryId) {
48434
+ const inputId = args2[0];
48435
+ if (!inputId) {
48402
48436
  return "Usage: /swarm knowledge quarantine <id> [reason]";
48403
48437
  }
48404
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
48438
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
48405
48439
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
48406
48440
  }
48407
48441
  const reason = args2.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
48408
48442
  try {
48409
- await quarantineEntry(directory, entryId, reason, "user");
48410
- return `✅ Entry ${entryId} quarantined successfully.`;
48443
+ const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
48444
+ const resolved = resolveEntryByPrefix(entries, inputId);
48445
+ if ("error" in resolved) {
48446
+ return `❌ ${resolved.error}`;
48447
+ }
48448
+ const fullId = resolved.entry.id;
48449
+ await quarantineEntry(directory, fullId, reason, "user");
48450
+ return `✅ Entry ${fullId} quarantined successfully.`;
48411
48451
  } catch (error93) {
48412
48452
  console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
48413
48453
  return `❌ Failed to quarantine entry. Check the entry ID and try again.`;
48414
48454
  }
48415
48455
  }
48416
48456
  async function handleKnowledgeRestoreCommand(directory, args2) {
48417
- const entryId = args2[0];
48418
- if (!entryId) {
48457
+ const inputId = args2[0];
48458
+ if (!inputId) {
48419
48459
  return "Usage: /swarm knowledge restore <id>";
48420
48460
  }
48421
- if (!/^[a-zA-Z0-9_-]{1,64}$/.test(entryId)) {
48461
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
48422
48462
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
48423
48463
  }
48424
48464
  try {
48425
- await restoreEntry(directory, entryId);
48426
- return `✅ Entry ${entryId} restored successfully.`;
48465
+ const quarantinePath = join28(directory, ".swarm", "knowledge-quarantined.jsonl");
48466
+ const entries = await readKnowledge(quarantinePath);
48467
+ const resolved = resolveEntryByPrefix(entries, inputId);
48468
+ if ("error" in resolved) {
48469
+ return `❌ ${resolved.error}`;
48470
+ }
48471
+ const fullId = resolved.entry.id;
48472
+ await restoreEntry(directory, fullId);
48473
+ return `✅ Entry ${fullId} restored successfully.`;
48427
48474
  } catch (error93) {
48428
48475
  console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
48429
48476
  return `❌ Failed to restore entry. Check the entry ID and try again.`;
@@ -48461,16 +48508,16 @@ async function handleKnowledgeListCommand(directory, _args) {
48461
48508
  const lines = [
48462
48509
  `## Knowledge Entries (${entries.length} total)`,
48463
48510
  "",
48464
- "| ID | Category | Confidence | Lesson (truncated) |",
48465
- "|------|----------|------------|---------------------|"
48511
+ "| ID (prefix) | Category | Confidence | Lesson (truncated) |",
48512
+ "|--------------|----------|------------|---------------------|"
48466
48513
  ];
48467
48514
  for (const entry of entries) {
48468
48515
  const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
48469
48516
  const confidencePct = Math.round(entry.confidence * 100);
48470
- lines.push(`| ${entry.id.slice(0, 8)}... | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
48517
+ lines.push(`| ${entry.id.slice(0, 12)} | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
48471
48518
  }
48472
48519
  lines.push("");
48473
- lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
48520
+ 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
48521
  return lines.join(`
48475
48522
  `);
48476
48523
  } catch (error93) {
@@ -58152,7 +58199,7 @@ function createSwarmAgents(swarmId, swarmConfig, isDefault, pluginConfig) {
58152
58199
  const prefix = isDefault ? "" : `${swarmId}_`;
58153
58200
  const swarmPrefix = isDefault ? undefined : swarmId;
58154
58201
  const qaRetryLimit = pluginConfig?.qa_retry_limit ?? 3;
58155
- const quiet = pluginConfig?.quiet ?? false;
58202
+ const quiet = pluginConfig?.quiet ?? true;
58156
58203
  const getModel = (baseName) => getModelForAgent(baseName, swarmAgents, swarmPrefix, quiet);
58157
58204
  const getPrompts = (name2) => loadAgentPrompt(name2);
58158
58205
  const prefixName = (name2) => `${prefix}${name2}`;
@@ -58302,7 +58349,7 @@ function getAgentConfigs(config3, directory, sessionId) {
58302
58349
  const agents = createAgents(config3);
58303
58350
  const toolFilterEnabled = config3?.tool_filter?.enabled ?? true;
58304
58351
  const toolFilterOverrides = config3?.tool_filter?.overrides ?? {};
58305
- const quiet = config3?.quiet ?? false;
58352
+ const quiet = config3?.quiet ?? true;
58306
58353
  const warnedMissingWhitelist = new Set;
58307
58354
  const agentToolSnapshot = {};
58308
58355
  const result = Object.fromEntries(agents.map((agent) => {
@@ -63841,7 +63888,7 @@ ${content.substring(endIndex + 1)}`;
63841
63888
  init_manager();
63842
63889
  init_utils2();
63843
63890
  import * as fs31 from "node:fs";
63844
- import { join as join41 } from "node:path";
63891
+ import { join as join42 } from "node:path";
63845
63892
  function createCompactionCustomizerHook(config3, directory) {
63846
63893
  const enabled = config3.hooks?.compaction !== false;
63847
63894
  if (!enabled) {
@@ -63886,7 +63933,7 @@ function createCompactionCustomizerHook(config3, directory) {
63886
63933
  }
63887
63934
  }
63888
63935
  try {
63889
- const summariesDir = join41(directory, ".swarm", "summaries");
63936
+ const summariesDir = join42(directory, ".swarm", "summaries");
63890
63937
  const files = await fs31.promises.readdir(summariesDir);
63891
63938
  if (files.length > 0) {
63892
63939
  const count = files.length;
@@ -74619,7 +74666,7 @@ import {
74619
74666
  readFileSync as readFileSync36,
74620
74667
  writeFileSync as writeFileSync11
74621
74668
  } from "node:fs";
74622
- import { join as join65 } from "node:path";
74669
+ import { join as join66 } from "node:path";
74623
74670
  var EVIDENCE_DIR2 = ".swarm/evidence";
74624
74671
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
74625
74672
  var COUNCIL_GATE_NAME = "council";
@@ -74653,9 +74700,9 @@ function writeCouncilEvidence(workingDir, synthesis) {
74653
74700
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
74654
74701
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
74655
74702
  }
74656
- const dir = join65(workingDir, EVIDENCE_DIR2);
74703
+ const dir = join66(workingDir, EVIDENCE_DIR2);
74657
74704
  mkdirSync18(dir, { recursive: true });
74658
- const filePath = join65(dir, `${synthesis.taskId}.json`);
74705
+ const filePath = join66(dir, `${synthesis.taskId}.json`);
74659
74706
  const existingRoot = Object.create(null);
74660
74707
  if (existsSync37(filePath)) {
74661
74708
  try {
@@ -74689,7 +74736,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
74689
74736
  updated.required_gates = [];
74690
74737
  writeFileSync11(filePath, JSON.stringify(updated, null, 2));
74691
74738
  try {
74692
- const councilDir = join65(workingDir, ".swarm", "council");
74739
+ const councilDir = join66(workingDir, ".swarm", "council");
74693
74740
  mkdirSync18(councilDir, { recursive: true });
74694
74741
  const auditLine = JSON.stringify({
74695
74742
  round: synthesis.roundNumber,
@@ -74697,7 +74744,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
74697
74744
  timestamp: synthesis.timestamp,
74698
74745
  vetoedBy: synthesis.vetoedBy
74699
74746
  });
74700
- appendFileSync6(join65(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
74747
+ appendFileSync6(join66(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
74701
74748
  `);
74702
74749
  } catch (auditError) {
74703
74750
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -74830,20 +74877,20 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
74830
74877
 
74831
74878
  // src/council/criteria-store.ts
74832
74879
  import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "node:fs";
74833
- import { join as join66 } from "node:path";
74880
+ import { join as join67 } from "node:path";
74834
74881
  var COUNCIL_DIR = ".swarm/council";
74835
74882
  function writeCriteria(workingDir, taskId, criteria) {
74836
- const dir = join66(workingDir, COUNCIL_DIR);
74883
+ const dir = join67(workingDir, COUNCIL_DIR);
74837
74884
  mkdirSync19(dir, { recursive: true });
74838
74885
  const payload = {
74839
74886
  taskId,
74840
74887
  criteria,
74841
74888
  declaredAt: new Date().toISOString()
74842
74889
  };
74843
- writeFileSync12(join66(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
74890
+ writeFileSync12(join67(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
74844
74891
  }
74845
74892
  function readCriteria(workingDir, taskId) {
74846
- const filePath = join66(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
74893
+ const filePath = join67(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
74847
74894
  if (!existsSync38(filePath))
74848
74895
  return null;
74849
74896
  try {
@@ -77388,6 +77435,7 @@ var VALID_CATEGORIES2 = [
77388
77435
  "debugging",
77389
77436
  "performance",
77390
77437
  "integration",
77438
+ "todo",
77391
77439
  "other"
77392
77440
  ];
77393
77441
  var knowledge_add = createSwarmTool({
@@ -77532,6 +77580,7 @@ var VALID_CATEGORIES3 = [
77532
77580
  "debugging",
77533
77581
  "performance",
77534
77582
  "integration",
77583
+ "todo",
77535
77584
  "other"
77536
77585
  ];
77537
77586
  var VALID_STATUSES = ["candidate", "established", "promoted"];
@@ -88668,7 +88717,7 @@ function readFileSafe(filePath) {
88668
88717
  return null;
88669
88718
  }
88670
88719
  }
88671
- function warnIfSwarmNotGitignored(directory) {
88720
+ function warnIfSwarmNotGitignored(directory, quiet = false) {
88672
88721
  if (_gitignoreWarningEmitted)
88673
88722
  return;
88674
88723
  try {
@@ -88686,7 +88735,9 @@ function warnIfSwarmNotGitignored(directory) {
88686
88735
  return;
88687
88736
  }
88688
88737
  _gitignoreWarningEmitted = true;
88689
- console.warn('[opencode-swarm] WARNING: .swarm/ is not in your .gitignore. Shell audit logs may contain API keys. Add ".swarm/" to your .gitignore to prevent accidental commits.');
88738
+ if (!quiet) {
88739
+ console.warn('[opencode-swarm] WARNING: .swarm/ is not in your .gitignore. Shell audit logs may contain API keys. Add ".swarm/" to your .gitignore to prevent accidental commits.');
88740
+ }
88690
88741
  } catch {}
88691
88742
  }
88692
88743
 
@@ -88802,7 +88853,7 @@ async function initializeOpenCodeSwarm(ctx) {
88802
88853
  await loadSnapshot(ctx.directory);
88803
88854
  initTelemetry(ctx.directory);
88804
88855
  writeSwarmConfigExampleIfNew(ctx.directory);
88805
- warnIfSwarmNotGitignored(ctx.directory);
88856
+ warnIfSwarmNotGitignored(ctx.directory, config3.quiet);
88806
88857
  if (config3.version_check !== false) {
88807
88858
  scheduleVersionCheck(package_default.version, (msg) => {
88808
88859
  if (config3.quiet) {
@@ -10,8 +10,8 @@ export declare function resetGitignoreWarningState(): void;
10
10
  /**
11
11
  * Checks whether `.swarm/` is covered by `.gitignore` or `.git/info/exclude`
12
12
  * in the git repo rooted at or above `directory`. If not covered, emits a
13
- * single `console.warn`. Fires at most once per process.
13
+ * single `console.warn` (unless `quiet` is true). Fires at most once per process.
14
14
  *
15
15
  * Never throws — any file-system error silently skips the check.
16
16
  */
17
- export declare function warnIfSwarmNotGitignored(directory: string): void;
17
+ export declare function warnIfSwarmNotGitignored(directory: string, quiet?: boolean): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.86.11",
3
+ "version": "6.86.13",
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",