opencode-swarm 7.46.1 → 7.46.3

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.46.1",
55
+ version: "7.46.3",
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",
@@ -37350,6 +37350,190 @@ var init_hive_promoter = __esm(() => {
37350
37350
  init_utils2();
37351
37351
  });
37352
37352
 
37353
+ // src/hooks/knowledge-events.ts
37354
+ import { existsSync as existsSync10 } from "fs";
37355
+ import { appendFile as appendFile4, mkdir as mkdir5, readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
37356
+ import * as path16 from "path";
37357
+ function resolveKnowledgeEventsPath(directory) {
37358
+ return path16.join(directory, ".swarm", "knowledge-events.jsonl");
37359
+ }
37360
+ function resolveLegacyApplicationLogPath(directory) {
37361
+ return path16.join(directory, ".swarm", "knowledge-application.jsonl");
37362
+ }
37363
+ async function readKnowledgeEvents(directory) {
37364
+ const filePath = resolveKnowledgeEventsPath(directory);
37365
+ if (!existsSync10(filePath))
37366
+ return [];
37367
+ const content = await readFile5(filePath, "utf-8");
37368
+ const out = [];
37369
+ for (const line of content.split(`
37370
+ `)) {
37371
+ const trimmed = line.trim();
37372
+ if (!trimmed)
37373
+ continue;
37374
+ try {
37375
+ out.push(JSON.parse(trimmed));
37376
+ } catch {
37377
+ warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
37378
+ }
37379
+ }
37380
+ return out;
37381
+ }
37382
+ async function readLegacyApplicationRecords(directory) {
37383
+ const filePath = resolveLegacyApplicationLogPath(directory);
37384
+ if (!existsSync10(filePath))
37385
+ return [];
37386
+ const content = await readFile5(filePath, "utf-8");
37387
+ const out = [];
37388
+ for (const line of content.split(`
37389
+ `)) {
37390
+ const trimmed = line.trim();
37391
+ if (!trimmed)
37392
+ continue;
37393
+ try {
37394
+ out.push(JSON.parse(trimmed));
37395
+ } catch {
37396
+ warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
37397
+ }
37398
+ }
37399
+ return out;
37400
+ }
37401
+ function emptyRollup() {
37402
+ return {
37403
+ shown_count: 0,
37404
+ acknowledged_count: 0,
37405
+ applied_explicit_count: 0,
37406
+ ignored_count: 0,
37407
+ violated_count: 0,
37408
+ contradicted_count: 0,
37409
+ succeeded_after_shown_count: 0,
37410
+ failed_after_shown_count: 0,
37411
+ partial_after_shown_count: 0
37412
+ };
37413
+ }
37414
+ function get(map3, id) {
37415
+ let r = map3.get(id);
37416
+ if (!r) {
37417
+ r = emptyRollup();
37418
+ map3.set(id, r);
37419
+ }
37420
+ return r;
37421
+ }
37422
+ function maxIso(current, candidate) {
37423
+ if (!current)
37424
+ return candidate;
37425
+ return candidate > current ? candidate : current;
37426
+ }
37427
+ function recomputeCounters(events, legacyRecords = []) {
37428
+ const map3 = new Map;
37429
+ const retrievedIds = new Set;
37430
+ for (const e of events) {
37431
+ switch (e.type) {
37432
+ case "retrieved": {
37433
+ for (const id of e.result_ids) {
37434
+ retrievedIds.add(id);
37435
+ get(map3, id).shown_count += 1;
37436
+ }
37437
+ break;
37438
+ }
37439
+ case "acknowledged": {
37440
+ const r = get(map3, e.knowledge_id);
37441
+ r.acknowledged_count += 1;
37442
+ r.last_acknowledged_at = maxIso(r.last_acknowledged_at, e.timestamp);
37443
+ break;
37444
+ }
37445
+ case "applied": {
37446
+ const r = get(map3, e.knowledge_id);
37447
+ r.applied_explicit_count += 1;
37448
+ r.last_applied_at = maxIso(r.last_applied_at, e.timestamp);
37449
+ break;
37450
+ }
37451
+ case "ignored":
37452
+ get(map3, e.knowledge_id).ignored_count += 1;
37453
+ break;
37454
+ case "violated":
37455
+ get(map3, e.knowledge_id).violated_count += 1;
37456
+ break;
37457
+ case "contradicted":
37458
+ get(map3, e.knowledge_id).contradicted_count += 1;
37459
+ break;
37460
+ case "outcome": {
37461
+ if (!e.knowledge_id)
37462
+ break;
37463
+ const r = get(map3, e.knowledge_id);
37464
+ if (e.outcome === "success")
37465
+ r.succeeded_after_shown_count += 1;
37466
+ else if (e.outcome === "failure")
37467
+ r.failed_after_shown_count += 1;
37468
+ else if (e.outcome === "partial")
37469
+ r.partial_after_shown_count += 1;
37470
+ break;
37471
+ }
37472
+ }
37473
+ }
37474
+ for (const rec of legacyRecords) {
37475
+ const r = get(map3, rec.knowledgeId);
37476
+ switch (rec.result) {
37477
+ case "shown":
37478
+ if (!retrievedIds.has(rec.knowledgeId))
37479
+ r.shown_count += 1;
37480
+ break;
37481
+ case "acknowledged":
37482
+ r.acknowledged_count += 1;
37483
+ r.last_acknowledged_at = maxIso(r.last_acknowledged_at, rec.timestamp);
37484
+ break;
37485
+ case "applied":
37486
+ r.applied_explicit_count += 1;
37487
+ r.last_applied_at = maxIso(r.last_applied_at, rec.timestamp);
37488
+ break;
37489
+ case "ignored":
37490
+ r.ignored_count += 1;
37491
+ break;
37492
+ case "violated":
37493
+ r.violated_count += 1;
37494
+ break;
37495
+ }
37496
+ }
37497
+ return map3;
37498
+ }
37499
+ async function readKnowledgeCounterRollups(directory) {
37500
+ try {
37501
+ const [events, legacyRecords] = await Promise.all([
37502
+ readKnowledgeEvents(directory),
37503
+ readLegacyApplicationRecords(directory)
37504
+ ]);
37505
+ return recomputeCounters(events, legacyRecords);
37506
+ } catch (err) {
37507
+ warn(`[knowledge-events] readKnowledgeCounterRollups failed: ${err instanceof Error ? err.message : String(err)}`);
37508
+ return new Map;
37509
+ }
37510
+ }
37511
+ function effectiveRetrievalOutcomes(stored, rollup) {
37512
+ const base = stored ?? {
37513
+ applied_count: 0,
37514
+ succeeded_after_count: 0,
37515
+ failed_after_count: 0
37516
+ };
37517
+ if (!rollup)
37518
+ return base;
37519
+ return {
37520
+ ...base,
37521
+ ...rollup
37522
+ };
37523
+ }
37524
+ var import_proper_lockfile5, RECEIPT_EVENT_TYPES;
37525
+ var init_knowledge_events = __esm(() => {
37526
+ init_logger();
37527
+ import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
37528
+ RECEIPT_EVENT_TYPES = new Set([
37529
+ "acknowledged",
37530
+ "applied",
37531
+ "ignored",
37532
+ "contradicted",
37533
+ "violated"
37534
+ ]);
37535
+ });
37536
+
37353
37537
  // src/hooks/knowledge-curator.ts
37354
37538
  function pruneSeenRetroSections() {
37355
37539
  const cutoff = Date.now() - 86400000;
@@ -37591,11 +37775,12 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
37591
37775
  async function runAutoPromotion(directory, config3) {
37592
37776
  const knowledgePath = resolveSwarmKnowledgePath(directory);
37593
37777
  const entries = await readKnowledge(knowledgePath) ?? [];
37778
+ const counterRollups = await readKnowledgeCounterRollups(directory);
37594
37779
  let changed = false;
37595
37780
  for (const entry of entries) {
37596
37781
  if (entry.status === "promoted")
37597
37782
  continue;
37598
- if (computeOutcomeSignal(entry.retrieval_outcomes) <= OUTCOME_PROMOTION_BLOCK) {
37783
+ if (computeOutcomeSignal(effectiveRetrievalOutcomes(entry.retrieval_outcomes, counterRollups.get(entry.id))) <= OUTCOME_PROMOTION_BLOCK) {
37599
37784
  continue;
37600
37785
  }
37601
37786
  const distinctPhases = new Set((entry.confirmed_by ?? []).map((c) => c.phase_number)).size;
@@ -37697,6 +37882,7 @@ function createKnowledgeCuratorHook(directory, config3) {
37697
37882
  }
37698
37883
  var seenRetroSections, OUTCOME_PROMOTION_BLOCK = -0.3, _internals11;
37699
37884
  var init_knowledge_curator = __esm(() => {
37885
+ init_knowledge_events();
37700
37886
  init_knowledge_store();
37701
37887
  init_knowledge_validator();
37702
37888
  init_utils2();
@@ -37819,11 +38005,11 @@ var init_skill_improver_llm_factory = __esm(() => {
37819
38005
  });
37820
38006
 
37821
38007
  // src/services/skill-improver-quota.ts
37822
- import { existsSync as existsSync10 } from "fs";
37823
- import { mkdir as mkdir5, readFile as readFile5, rename as rename4, writeFile as writeFile6 } from "fs/promises";
37824
- import * as path16 from "path";
38008
+ import { existsSync as existsSync11 } from "fs";
38009
+ import { mkdir as mkdir6, readFile as readFile6, rename as rename4, writeFile as writeFile7 } from "fs/promises";
38010
+ import * as path17 from "path";
37825
38011
  async function acquireLock(dir) {
37826
- const acquire = import_proper_lockfile5.default.lock(dir, LOCK_RETRY_OPTS);
38012
+ const acquire = import_proper_lockfile6.default.lock(dir, LOCK_RETRY_OPTS);
37827
38013
  let timer;
37828
38014
  const timeout = new Promise((_, reject) => {
37829
38015
  timer = setTimeout(() => {
@@ -37839,7 +38025,7 @@ async function acquireLock(dir) {
37839
38025
  }
37840
38026
  }
37841
38027
  function resolveQuotaPath(directory) {
37842
- return path16.join(directory, ".swarm", "skill-improver-quota.json");
38028
+ return path17.join(directory, ".swarm", "skill-improver-quota.json");
37843
38029
  }
37844
38030
  function todayKey(window, now = new Date) {
37845
38031
  if (window === "utc") {
@@ -37851,10 +38037,10 @@ function todayKey(window, now = new Date) {
37851
38037
  return `${yr}-${m}-${d}`;
37852
38038
  }
37853
38039
  async function readState(filePath) {
37854
- if (!existsSync10(filePath))
38040
+ if (!existsSync11(filePath))
37855
38041
  return null;
37856
38042
  try {
37857
- const raw = await readFile5(filePath, "utf-8");
38043
+ const raw = await readFile6(filePath, "utf-8");
37858
38044
  const parsed = JSON.parse(raw);
37859
38045
  if (typeof parsed.date !== "string" || typeof parsed.calls_used !== "number" || typeof parsed.max_calls !== "number" || parsed.window !== "utc" && parsed.window !== "local") {
37860
38046
  return null;
@@ -37865,9 +38051,9 @@ async function readState(filePath) {
37865
38051
  }
37866
38052
  }
37867
38053
  async function writeState(filePath, state) {
37868
- await mkdir5(path16.dirname(filePath), { recursive: true });
38054
+ await mkdir6(path17.dirname(filePath), { recursive: true });
37869
38055
  const tmp = `${filePath}.tmp-${process.pid}`;
37870
- await writeFile6(tmp, JSON.stringify(state, null, 2), "utf-8");
38056
+ await writeFile7(tmp, JSON.stringify(state, null, 2), "utf-8");
37871
38057
  await rename4(tmp, filePath);
37872
38058
  }
37873
38059
  async function getQuotaState(directory, opts) {
@@ -37888,10 +38074,10 @@ async function getQuotaState(directory, opts) {
37888
38074
  }
37889
38075
  async function reserveQuota(directory, opts) {
37890
38076
  const filePath = resolveQuotaPath(directory);
37891
- await mkdir5(path16.dirname(filePath), { recursive: true });
38077
+ await mkdir6(path17.dirname(filePath), { recursive: true });
37892
38078
  let release = null;
37893
38079
  try {
37894
- release = await acquireLock(path16.dirname(filePath));
38080
+ release = await acquireLock(path17.dirname(filePath));
37895
38081
  const state = await getQuotaState(directory, opts);
37896
38082
  if (state.calls_used + opts.nCalls > opts.maxCalls) {
37897
38083
  return {
@@ -37918,10 +38104,10 @@ async function reserveQuota(directory, opts) {
37918
38104
  }
37919
38105
  async function releaseQuota(directory, opts) {
37920
38106
  const filePath = resolveQuotaPath(directory);
37921
- await mkdir5(path16.dirname(filePath), { recursive: true });
38107
+ await mkdir6(path17.dirname(filePath), { recursive: true });
37922
38108
  let release = null;
37923
38109
  try {
37924
- release = await acquireLock(path16.dirname(filePath));
38110
+ release = await acquireLock(path17.dirname(filePath));
37925
38111
  const state = await getQuotaState(directory, opts);
37926
38112
  const next = {
37927
38113
  ...state,
@@ -37938,9 +38124,9 @@ async function releaseQuota(directory, opts) {
37938
38124
  }
37939
38125
  }
37940
38126
  }
37941
- var import_proper_lockfile5, LOCK_ACQUIRE_TIMEOUT_MS = 1e4, LOCK_RETRY_OPTS;
38127
+ var import_proper_lockfile6, LOCK_ACQUIRE_TIMEOUT_MS = 1e4, LOCK_RETRY_OPTS;
37942
38128
  var init_skill_improver_quota = __esm(() => {
37943
- import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
38129
+ import_proper_lockfile6 = __toESM(require_proper_lockfile(), 1);
37944
38130
  LOCK_RETRY_OPTS = {
37945
38131
  retries: {
37946
38132
  retries: 30,
@@ -37953,22 +38139,22 @@ var init_skill_improver_quota = __esm(() => {
37953
38139
  });
37954
38140
 
37955
38141
  // src/services/skill-improver.ts
37956
- import { existsSync as existsSync11 } from "fs";
37957
- import { mkdir as mkdir6, rename as rename5, writeFile as writeFile7 } from "fs/promises";
37958
- import * as path17 from "path";
38142
+ import { existsSync as existsSync12 } from "fs";
38143
+ import { mkdir as mkdir7, rename as rename5, writeFile as writeFile8 } from "fs/promises";
38144
+ import * as path18 from "path";
37959
38145
  function timestampSlug(d) {
37960
38146
  return d.toISOString().replace(/[:.]/g, "-");
37961
38147
  }
37962
38148
  async function atomicWrite2(p, content) {
37963
- await mkdir6(path17.dirname(p), { recursive: true });
38149
+ await mkdir7(path18.dirname(p), { recursive: true });
37964
38150
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
37965
- await writeFile7(tmp, content, "utf-8");
38151
+ await writeFile8(tmp, content, "utf-8");
37966
38152
  await rename5(tmp, p);
37967
38153
  }
37968
38154
  async function gatherInventory(directory) {
37969
38155
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
37970
38156
  const hivePath = resolveHiveKnowledgePath();
37971
- const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
38157
+ const hive = existsSync12(hivePath) ? await readKnowledge(hivePath) : [];
37972
38158
  const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
37973
38159
  const skills = await listSkills(directory);
37974
38160
  const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
@@ -38241,8 +38427,8 @@ async function runSkillImprover(req) {
38241
38427
  }
38242
38428
  throw err;
38243
38429
  }
38244
- const proposalDir = path17.join(req.directory, ".swarm", "skill-improver", "proposals");
38245
- const proposalFile = path17.join(proposalDir, `${timestampSlug(now)}.md`);
38430
+ const proposalDir = path18.join(req.directory, ".swarm", "skill-improver", "proposals");
38431
+ const proposalFile = path18.join(proposalDir, `${timestampSlug(now)}.md`);
38246
38432
  const finalBody = source === "llm" ? buildLLMProposalFrame({
38247
38433
  body,
38248
38434
  targets,
@@ -38638,7 +38824,7 @@ var init_write_retro = __esm(() => {
38638
38824
 
38639
38825
  // src/commands/close.ts
38640
38826
  import { promises as fs8 } from "fs";
38641
- import path18 from "path";
38827
+ import path19 from "path";
38642
38828
  async function runAbortableSkillReview(req, timeoutMs) {
38643
38829
  const controller = new AbortController;
38644
38830
  let timeout;
@@ -38694,10 +38880,10 @@ function guaranteeAllPlansComplete(planData) {
38694
38880
  }
38695
38881
  async function handleCloseCommand(directory, args, options = {}) {
38696
38882
  const planPath = validateSwarmPath(directory, "plan.json");
38697
- const swarmDir = path18.join(directory, ".swarm");
38883
+ const swarmDir = path19.join(directory, ".swarm");
38698
38884
  let planExists = false;
38699
38885
  let planData = {
38700
- title: path18.basename(directory) || "Ad-hoc session",
38886
+ title: path19.basename(directory) || "Ad-hoc session",
38701
38887
  phases: []
38702
38888
  };
38703
38889
  try {
@@ -38806,7 +38992,7 @@ async function handleCloseCommand(directory, args, options = {}) {
38806
38992
  warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
38807
38993
  }
38808
38994
  }
38809
- const lessonsFilePath = path18.join(swarmDir, "close-lessons.md");
38995
+ const lessonsFilePath = path19.join(swarmDir, "close-lessons.md");
38810
38996
  let explicitLessons = [];
38811
38997
  try {
38812
38998
  const lessonsText = await fs8.readFile(lessonsFilePath, "utf-8");
@@ -38815,11 +39001,11 @@ async function handleCloseCommand(directory, args, options = {}) {
38815
39001
  } catch {}
38816
39002
  const retroLessons = [];
38817
39003
  try {
38818
- const evidenceDir = path18.join(swarmDir, "evidence");
39004
+ const evidenceDir = path19.join(swarmDir, "evidence");
38819
39005
  const evidenceEntries = await fs8.readdir(evidenceDir);
38820
39006
  const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
38821
39007
  for (const retroDir of retroDirs) {
38822
- const evidencePath = path18.join(evidenceDir, retroDir, "evidence.json");
39008
+ const evidencePath = path19.join(evidenceDir, retroDir, "evidence.json");
38823
39009
  try {
38824
39010
  const content = await fs8.readFile(evidencePath, "utf-8");
38825
39011
  const parsed = JSON.parse(content);
@@ -38954,7 +39140,7 @@ async function handleCloseCommand(directory, args, options = {}) {
38954
39140
  }
38955
39141
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
38956
39142
  const suffix = Math.random().toString(36).slice(2, 8);
38957
- const archiveDir = path18.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
39143
+ const archiveDir = path19.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
38958
39144
  let archiveResult = "";
38959
39145
  let archivedFileCount = 0;
38960
39146
  const archivedActiveStateFiles = new Set;
@@ -38962,8 +39148,8 @@ async function handleCloseCommand(directory, args, options = {}) {
38962
39148
  try {
38963
39149
  await fs8.mkdir(archiveDir, { recursive: true });
38964
39150
  for (const artifact of ARCHIVE_ARTIFACTS) {
38965
- const srcPath = path18.join(swarmDir, artifact);
38966
- const destPath = path18.join(archiveDir, artifact);
39151
+ const srcPath = path19.join(swarmDir, artifact);
39152
+ const destPath = path19.join(archiveDir, artifact);
38967
39153
  try {
38968
39154
  await fs8.copyFile(srcPath, destPath);
38969
39155
  archivedFileCount++;
@@ -38973,22 +39159,22 @@ async function handleCloseCommand(directory, args, options = {}) {
38973
39159
  } catch {}
38974
39160
  }
38975
39161
  for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
38976
- const srcDir = path18.join(swarmDir, dirName);
38977
- const destDir = path18.join(archiveDir, dirName);
39162
+ const srcDir = path19.join(swarmDir, dirName);
39163
+ const destDir = path19.join(archiveDir, dirName);
38978
39164
  try {
38979
39165
  const entries = await fs8.readdir(srcDir);
38980
39166
  if (entries.length > 0) {
38981
39167
  await fs8.mkdir(destDir, { recursive: true });
38982
39168
  for (const entry of entries) {
38983
- const srcEntry = path18.join(srcDir, entry);
38984
- const destEntry = path18.join(destDir, entry);
39169
+ const srcEntry = path19.join(srcDir, entry);
39170
+ const destEntry = path19.join(destDir, entry);
38985
39171
  try {
38986
39172
  const stat2 = await fs8.stat(srcEntry);
38987
39173
  if (stat2.isDirectory()) {
38988
39174
  await fs8.mkdir(destEntry, { recursive: true });
38989
39175
  const subEntries = await fs8.readdir(srcEntry);
38990
39176
  for (const sub of subEntries) {
38991
- await fs8.copyFile(path18.join(srcEntry, sub), path18.join(destEntry, sub)).catch(() => {});
39177
+ await fs8.copyFile(path19.join(srcEntry, sub), path19.join(destEntry, sub)).catch(() => {});
38992
39178
  }
38993
39179
  } else {
38994
39180
  await fs8.copyFile(srcEntry, destEntry);
@@ -39020,7 +39206,7 @@ async function handleCloseCommand(directory, args, options = {}) {
39020
39206
  warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
39021
39207
  continue;
39022
39208
  }
39023
- const filePath = path18.join(swarmDir, artifact);
39209
+ const filePath = path19.join(swarmDir, artifact);
39024
39210
  try {
39025
39211
  await fs8.unlink(filePath);
39026
39212
  cleanedFiles.push(artifact);
@@ -39033,7 +39219,7 @@ async function handleCloseCommand(directory, args, options = {}) {
39033
39219
  if (!archivedActiveStateDirs.has(dirName)) {
39034
39220
  continue;
39035
39221
  }
39036
- const dirPath = path18.join(swarmDir, dirName);
39222
+ const dirPath = path19.join(swarmDir, dirName);
39037
39223
  try {
39038
39224
  await fs8.rm(dirPath, { recursive: true, force: true });
39039
39225
  cleanedFiles.push(`${dirName}/`);
@@ -39044,23 +39230,23 @@ async function handleCloseCommand(directory, args, options = {}) {
39044
39230
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
39045
39231
  for (const backup of configBackups) {
39046
39232
  try {
39047
- await fs8.unlink(path18.join(swarmDir, backup));
39233
+ await fs8.unlink(path19.join(swarmDir, backup));
39048
39234
  configBackupsRemoved++;
39049
39235
  } catch {}
39050
39236
  }
39051
39237
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
39052
39238
  for (const sibling of ledgerSiblings) {
39053
39239
  try {
39054
- await fs8.unlink(path18.join(swarmDir, sibling));
39240
+ await fs8.unlink(path19.join(swarmDir, sibling));
39055
39241
  } catch {}
39056
39242
  }
39057
39243
  } catch {}
39058
39244
  let swarmPlanFilesRemoved = 0;
39059
39245
  const candidates = [
39060
- path18.join(directory, ".swarm", "SWARM_PLAN.json"),
39061
- path18.join(directory, ".swarm", "SWARM_PLAN.md"),
39062
- path18.join(directory, "SWARM_PLAN.json"),
39063
- path18.join(directory, "SWARM_PLAN.md")
39246
+ path19.join(directory, ".swarm", "SWARM_PLAN.json"),
39247
+ path19.join(directory, ".swarm", "SWARM_PLAN.md"),
39248
+ path19.join(directory, "SWARM_PLAN.json"),
39249
+ path19.join(directory, "SWARM_PLAN.md")
39064
39250
  ];
39065
39251
  for (const candidate of candidates) {
39066
39252
  try {
@@ -39068,12 +39254,12 @@ async function handleCloseCommand(directory, args, options = {}) {
39068
39254
  swarmPlanFilesRemoved++;
39069
39255
  } catch (err) {
39070
39256
  if (err?.code !== "ENOENT") {
39071
- warnings.push(`Failed to remove ${path18.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
39257
+ warnings.push(`Failed to remove ${path19.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
39072
39258
  }
39073
39259
  }
39074
39260
  }
39075
39261
  clearAllScopes(directory);
39076
- const contextPath = path18.join(swarmDir, "context.md");
39262
+ const contextPath = path19.join(swarmDir, "context.md");
39077
39263
  const contextContent = [
39078
39264
  "# Context",
39079
39265
  "",
@@ -39397,14 +39583,14 @@ var init_concurrency = __esm(() => {
39397
39583
 
39398
39584
  // src/commands/config.ts
39399
39585
  import * as os4 from "os";
39400
- import * as path19 from "path";
39586
+ import * as path20 from "path";
39401
39587
  function getUserConfigDir2() {
39402
- return process.env.XDG_CONFIG_HOME || path19.join(os4.homedir(), ".config");
39588
+ return process.env.XDG_CONFIG_HOME || path20.join(os4.homedir(), ".config");
39403
39589
  }
39404
39590
  async function handleConfigCommand(directory, _args) {
39405
39591
  const config3 = loadPluginConfig(directory);
39406
- const userConfigPath = path19.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
39407
- const projectConfigPath = path19.join(directory, ".opencode", "opencode-swarm.json");
39592
+ const userConfigPath = path20.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
39593
+ const projectConfigPath = path20.join(directory, ".opencode", "opencode-swarm.json");
39408
39594
  const lines = [
39409
39595
  "## Swarm Configuration",
39410
39596
  "",
@@ -39530,8 +39716,8 @@ var init_curate = __esm(() => {
39530
39716
  // src/tools/co-change-analyzer.ts
39531
39717
  import * as child_process3 from "child_process";
39532
39718
  import { randomUUID as randomUUID2 } from "crypto";
39533
- import { readdir, readFile as readFile6, stat as stat2 } from "fs/promises";
39534
- import * as path20 from "path";
39719
+ import { readdir, readFile as readFile7, stat as stat2 } from "fs/promises";
39720
+ import * as path21 from "path";
39535
39721
  import { promisify } from "util";
39536
39722
  function getExecFileAsync() {
39537
39723
  return promisify(child_process3.execFile);
@@ -39635,7 +39821,7 @@ async function scanSourceFiles(dir) {
39635
39821
  try {
39636
39822
  const entries = await readdir(dir, { withFileTypes: true });
39637
39823
  for (const entry of entries) {
39638
- const fullPath = path20.join(dir, entry.name);
39824
+ const fullPath = path21.join(dir, entry.name);
39639
39825
  if (entry.isDirectory()) {
39640
39826
  if (skipDirs.has(entry.name)) {
39641
39827
  continue;
@@ -39643,7 +39829,7 @@ async function scanSourceFiles(dir) {
39643
39829
  const subFiles = await scanSourceFiles(fullPath);
39644
39830
  results.push(...subFiles);
39645
39831
  } else if (entry.isFile()) {
39646
- const ext = path20.extname(entry.name);
39832
+ const ext = path21.extname(entry.name);
39647
39833
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
39648
39834
  results.push(fullPath);
39649
39835
  }
@@ -39657,7 +39843,7 @@ async function getStaticEdges(directory) {
39657
39843
  const sourceFiles = await scanSourceFiles(directory);
39658
39844
  for (const sourceFile of sourceFiles) {
39659
39845
  try {
39660
- const content = await readFile6(sourceFile, "utf-8");
39846
+ const content = await readFile7(sourceFile, "utf-8");
39661
39847
  const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
39662
39848
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
39663
39849
  const importPath = match[1].trim();
@@ -39665,8 +39851,8 @@ async function getStaticEdges(directory) {
39665
39851
  continue;
39666
39852
  }
39667
39853
  try {
39668
- const sourceDir = path20.dirname(sourceFile);
39669
- const resolvedPath = path20.resolve(sourceDir, importPath);
39854
+ const sourceDir = path21.dirname(sourceFile);
39855
+ const resolvedPath = path21.resolve(sourceDir, importPath);
39670
39856
  const extensions = [
39671
39857
  "",
39672
39858
  ".ts",
@@ -39691,8 +39877,8 @@ async function getStaticEdges(directory) {
39691
39877
  if (!targetFile) {
39692
39878
  continue;
39693
39879
  }
39694
- const relSource = path20.relative(directory, sourceFile).replace(/\\/g, "/");
39695
- const relTarget = path20.relative(directory, targetFile).replace(/\\/g, "/");
39880
+ const relSource = path21.relative(directory, sourceFile).replace(/\\/g, "/");
39881
+ const relTarget = path21.relative(directory, targetFile).replace(/\\/g, "/");
39696
39882
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
39697
39883
  edges.add(key);
39698
39884
  } catch {}
@@ -39704,7 +39890,7 @@ async function getStaticEdges(directory) {
39704
39890
  function isTestImplementationPair(fileA, fileB) {
39705
39891
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
39706
39892
  const getBaseName = (filePath) => {
39707
- const base = path20.basename(filePath);
39893
+ const base = path21.basename(filePath);
39708
39894
  for (const pattern of testPatterns) {
39709
39895
  if (base.endsWith(pattern)) {
39710
39896
  return base.slice(0, -pattern.length);
@@ -39714,16 +39900,16 @@ function isTestImplementationPair(fileA, fileB) {
39714
39900
  };
39715
39901
  const baseA = getBaseName(fileA);
39716
39902
  const baseB = getBaseName(fileB);
39717
- return baseA === baseB && baseA !== path20.basename(fileA) && baseA !== path20.basename(fileB);
39903
+ return baseA === baseB && baseA !== path21.basename(fileA) && baseA !== path21.basename(fileB);
39718
39904
  }
39719
39905
  function hasSharedPrefix(fileA, fileB) {
39720
- const dirA = path20.dirname(fileA);
39721
- const dirB = path20.dirname(fileB);
39906
+ const dirA = path21.dirname(fileA);
39907
+ const dirB = path21.dirname(fileB);
39722
39908
  if (dirA !== dirB) {
39723
39909
  return false;
39724
39910
  }
39725
- const baseA = path20.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
39726
- const baseB = path20.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
39911
+ const baseA = path21.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
39912
+ const baseB = path21.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
39727
39913
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
39728
39914
  return true;
39729
39915
  }
@@ -39778,8 +39964,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
39778
39964
  const entries = [];
39779
39965
  const now = new Date().toISOString();
39780
39966
  for (const pair of pairs.slice(0, 10)) {
39781
- const baseA = path20.basename(pair.fileA);
39782
- const baseB = path20.basename(pair.fileB);
39967
+ const baseA = path21.basename(pair.fileA);
39968
+ const baseB = path21.basename(pair.fileB);
39783
39969
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
39784
39970
  if (lesson.length > 280) {
39785
39971
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -39881,7 +40067,7 @@ var init_co_change_analyzer = __esm(() => {
39881
40067
  });
39882
40068
 
39883
40069
  // src/commands/dark-matter.ts
39884
- import path21 from "path";
40070
+ import path22 from "path";
39885
40071
  async function handleDarkMatterCommand(directory, args) {
39886
40072
  const options = {};
39887
40073
  for (let i = 0;i < args.length; i++) {
@@ -39913,7 +40099,7 @@ Ensure this is a git repository with commit history.`;
39913
40099
  const output = formatDarkMatterOutput(pairs);
39914
40100
  if (pairs.length > 0) {
39915
40101
  try {
39916
- const projectName = path21.basename(path21.resolve(directory));
40102
+ const projectName = path22.basename(path22.resolve(directory));
39917
40103
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
39918
40104
  if (entries.length > 0) {
39919
40105
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -40050,44 +40236,44 @@ var init_deep_dive = __esm(() => {
40050
40236
 
40051
40237
  // src/config/cache-paths.ts
40052
40238
  import * as os5 from "os";
40053
- import * as path22 from "path";
40239
+ import * as path23 from "path";
40054
40240
  function getPluginConfigDir() {
40055
- return path22.join(process.env.XDG_CONFIG_HOME || path22.join(os5.homedir(), ".config"), "opencode");
40241
+ return path23.join(process.env.XDG_CONFIG_HOME || path23.join(os5.homedir(), ".config"), "opencode");
40056
40242
  }
40057
40243
  function getPluginCachePaths() {
40058
- const cacheBase = process.env.XDG_CACHE_HOME || path22.join(os5.homedir(), ".cache");
40244
+ const cacheBase = process.env.XDG_CACHE_HOME || path23.join(os5.homedir(), ".cache");
40059
40245
  const configDir = getPluginConfigDir();
40060
40246
  const paths = [
40061
- path22.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
40062
- path22.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
40063
- path22.join(configDir, "node_modules", "opencode-swarm")
40247
+ path23.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
40248
+ path23.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
40249
+ path23.join(configDir, "node_modules", "opencode-swarm")
40064
40250
  ];
40065
40251
  if (process.platform === "darwin") {
40066
- const libCaches = path22.join(os5.homedir(), "Library", "Caches");
40067
- paths.push(path22.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path22.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
40252
+ const libCaches = path23.join(os5.homedir(), "Library", "Caches");
40253
+ paths.push(path23.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path23.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
40068
40254
  }
40069
40255
  if (process.platform === "win32") {
40070
- const localAppData = process.env.LOCALAPPDATA || path22.join(os5.homedir(), "AppData", "Local");
40071
- const appData = process.env.APPDATA || path22.join(os5.homedir(), "AppData", "Roaming");
40072
- paths.push(path22.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path22.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path22.join(appData, "opencode", "node_modules", "opencode-swarm"));
40256
+ const localAppData = process.env.LOCALAPPDATA || path23.join(os5.homedir(), "AppData", "Local");
40257
+ const appData = process.env.APPDATA || path23.join(os5.homedir(), "AppData", "Roaming");
40258
+ paths.push(path23.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path23.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path23.join(appData, "opencode", "node_modules", "opencode-swarm"));
40073
40259
  }
40074
40260
  return paths;
40075
40261
  }
40076
40262
  function getPluginLockFilePaths() {
40077
- const cacheBase = process.env.XDG_CACHE_HOME || path22.join(os5.homedir(), ".cache");
40263
+ const cacheBase = process.env.XDG_CACHE_HOME || path23.join(os5.homedir(), ".cache");
40078
40264
  const configDir = getPluginConfigDir();
40079
40265
  const paths = [
40080
- path22.join(cacheBase, "opencode", "bun.lock"),
40081
- path22.join(cacheBase, "opencode", "bun.lockb"),
40082
- path22.join(configDir, "package-lock.json")
40266
+ path23.join(cacheBase, "opencode", "bun.lock"),
40267
+ path23.join(cacheBase, "opencode", "bun.lockb"),
40268
+ path23.join(configDir, "package-lock.json")
40083
40269
  ];
40084
40270
  if (process.platform === "darwin") {
40085
- const libCaches = path22.join(os5.homedir(), "Library", "Caches");
40086
- paths.push(path22.join(libCaches, "opencode", "bun.lock"), path22.join(libCaches, "opencode", "bun.lockb"));
40271
+ const libCaches = path23.join(os5.homedir(), "Library", "Caches");
40272
+ paths.push(path23.join(libCaches, "opencode", "bun.lock"), path23.join(libCaches, "opencode", "bun.lockb"));
40087
40273
  }
40088
40274
  if (process.platform === "win32") {
40089
- const localAppData = process.env.LOCALAPPDATA || path22.join(os5.homedir(), "AppData", "Local");
40090
- paths.push(path22.join(localAppData, "opencode", "bun.lock"), path22.join(localAppData, "opencode", "bun.lockb"));
40275
+ const localAppData = process.env.LOCALAPPDATA || path23.join(os5.homedir(), "AppData", "Local");
40276
+ paths.push(path23.join(localAppData, "opencode", "bun.lock"), path23.join(localAppData, "opencode", "bun.lockb"));
40091
40277
  }
40092
40278
  return paths;
40093
40279
  }
@@ -40269,45 +40455,6 @@ var init_gate_bridge = __esm(() => {
40269
40455
  };
40270
40456
  });
40271
40457
 
40272
- // src/hooks/knowledge-events.ts
40273
- import { existsSync as existsSync12 } from "fs";
40274
- import { appendFile as appendFile4, mkdir as mkdir7, readFile as readFile7 } from "fs/promises";
40275
- import * as path23 from "path";
40276
- function resolveKnowledgeEventsPath(directory) {
40277
- return path23.join(directory, ".swarm", "knowledge-events.jsonl");
40278
- }
40279
- async function readKnowledgeEvents(directory) {
40280
- const filePath = resolveKnowledgeEventsPath(directory);
40281
- if (!existsSync12(filePath))
40282
- return [];
40283
- const content = await readFile7(filePath, "utf-8");
40284
- const out = [];
40285
- for (const line of content.split(`
40286
- `)) {
40287
- const trimmed = line.trim();
40288
- if (!trimmed)
40289
- continue;
40290
- try {
40291
- out.push(JSON.parse(trimmed));
40292
- } catch {
40293
- warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
40294
- }
40295
- }
40296
- return out;
40297
- }
40298
- var RECEIPT_EVENT_TYPES;
40299
- var init_knowledge_events = __esm(() => {
40300
- init_logger();
40301
- init_knowledge_store();
40302
- RECEIPT_EVENT_TYPES = new Set([
40303
- "acknowledged",
40304
- "applied",
40305
- "ignored",
40306
- "contradicted",
40307
- "violated"
40308
- ]);
40309
- });
40310
-
40311
40458
  // src/services/version-check.ts
40312
40459
  import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
40313
40460
  import { homedir as homedir5 } from "os";
@@ -44402,7 +44549,7 @@ function withStateLock(directory, fn) {
44402
44549
  fs12.writeFileSync(lockTarget, `${JSON.stringify(seed, null, 2)}
44403
44550
  `, "utf-8");
44404
44551
  }
44405
- release = lockfile6.lockSync(lockTarget, {
44552
+ release = lockfile7.lockSync(lockTarget, {
44406
44553
  retries: { retries: 5, minTimeout: 5, maxTimeout: 50 },
44407
44554
  stale: 5000
44408
44555
  });
@@ -44588,12 +44735,12 @@ function terminateFullAutoRun(directory, sessionID, reason) {
44588
44735
  return state;
44589
44736
  });
44590
44737
  }
44591
- var import_proper_lockfile6, lockfile6, STATE_FILE = "full-auto-state.json", stateUnreadable = false, stateUnreadableReason = "";
44738
+ var import_proper_lockfile7, lockfile7, STATE_FILE = "full-auto-state.json", stateUnreadable = false, stateUnreadableReason = "";
44592
44739
  var init_state2 = __esm(() => {
44593
44740
  init_utils2();
44594
44741
  init_logger();
44595
- import_proper_lockfile6 = __toESM(require_proper_lockfile(), 1);
44596
- lockfile6 = import_proper_lockfile6.default;
44742
+ import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
44743
+ lockfile7 = import_proper_lockfile7.default;
44597
44744
  });
44598
44745
 
44599
44746
  // src/commands/full-auto.ts
@@ -45619,7 +45766,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
45619
45766
  // src/hooks/knowledge-migrator.ts
45620
45767
  import { randomUUID as randomUUID3 } from "crypto";
45621
45768
  import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
45622
- import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
45769
+ import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
45623
45770
  import * as path30 from "path";
45624
45771
  async function migrateKnowledgeToExternal(_directory, _config) {
45625
45772
  return {
@@ -45850,7 +45997,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
45850
45997
  migration_tool: "knowledge-migrator.ts"
45851
45998
  };
45852
45999
  await mkdir8(path30.dirname(sentinelPath), { recursive: true });
45853
- await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
46000
+ await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
45854
46001
  }
45855
46002
  var _internals19;
45856
46003
  var init_knowledge_migrator = __esm(() => {
@@ -46903,7 +47050,7 @@ import {
46903
47050
  mkdir as mkdir9,
46904
47051
  readFile as readFile10,
46905
47052
  rename as rename6,
46906
- writeFile as writeFile9
47053
+ writeFile as writeFile10
46907
47054
  } from "fs/promises";
46908
47055
  import * as path31 from "path";
46909
47056
 
@@ -47314,7 +47461,7 @@ async function writeJsonlAtomic(filePath, values) {
47314
47461
  const content = values.map((value) => JSON.stringify(value)).join(`
47315
47462
  `) + (values.length > 0 ? `
47316
47463
  ` : "");
47317
- await writeFile9(tmp, content, "utf-8");
47464
+ await writeFile10(tmp, content, "utf-8");
47318
47465
  await rename6(tmp, filePath);
47319
47466
  }
47320
47467
  var init_local_jsonl_provider = __esm(() => {
@@ -47335,7 +47482,7 @@ var init_prompt_block = __esm(() => {
47335
47482
 
47336
47483
  // src/memory/jsonl-migration.ts
47337
47484
  import { existsSync as existsSync22 } from "fs";
47338
- import { copyFile, mkdir as mkdir10, readFile as readFile11, stat as stat3, writeFile as writeFile10 } from "fs/promises";
47485
+ import { copyFile, mkdir as mkdir10, readFile as readFile11, stat as stat3, writeFile as writeFile11 } from "fs/promises";
47339
47486
  import * as path32 from "path";
47340
47487
  function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
47341
47488
  const resolved = resolveConfig(config3);
@@ -47383,14 +47530,14 @@ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
47383
47530
  await mkdir10(exportDir, { recursive: true });
47384
47531
  const memoriesPath = path32.join(exportDir, "memories.jsonl");
47385
47532
  const proposalsPath = path32.join(exportDir, "proposals.jsonl");
47386
- await writeFile10(memoriesPath, toJsonl(memories), "utf-8");
47387
- await writeFile10(proposalsPath, toJsonl(proposals), "utf-8");
47533
+ await writeFile11(memoriesPath, toJsonl(memories), "utf-8");
47534
+ await writeFile11(proposalsPath, toJsonl(proposals), "utf-8");
47388
47535
  return { directory: exportDir, memoriesPath, proposalsPath };
47389
47536
  }
47390
47537
  async function writeMigrationReport(rootDirectory, report, config3 = {}) {
47391
47538
  const reportPath = path32.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
47392
47539
  await mkdir10(path32.dirname(reportPath), { recursive: true });
47393
- await writeFile10(reportPath, `${JSON.stringify(report, null, 2)}
47540
+ await writeFile11(reportPath, `${JSON.stringify(report, null, 2)}
47394
47541
  `, "utf-8");
47395
47542
  return reportPath;
47396
47543
  }