opencode-swarm 7.87.0 → 7.87.2

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/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.87.0",
72
+ version: "7.87.2",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -18060,6 +18060,24 @@ var init_git_binary_missing_error = __esm(() => {
18060
18060
  };
18061
18061
  });
18062
18062
 
18063
+ // src/utils/transient-retry.ts
18064
+ function isTransientSpawnError(error49) {
18065
+ if (!error49 || typeof error49 !== "object")
18066
+ return false;
18067
+ const code = error49.code;
18068
+ return code === "ETIMEDOUT";
18069
+ }
18070
+ function transientBackoff(attempt) {
18071
+ const delay = RETRY_BASE_DELAY_MS * 2 ** attempt;
18072
+ try {
18073
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delay);
18074
+ } catch {
18075
+ const start2 = Date.now();
18076
+ while (Date.now() - start2 < delay) {}
18077
+ }
18078
+ }
18079
+ var MAX_TRANSIENT_RETRIES = 5, RETRY_BASE_DELAY_MS = 200;
18080
+
18063
18081
  // src/git/branch.ts
18064
18082
  import * as child_process from "node:child_process";
18065
18083
  import path6 from "node:path";
@@ -18092,26 +18110,34 @@ function gitExec(args2, cwd) {
18092
18110
  const subcommand = args2[0];
18093
18111
  const hardenedArgs = subcommand === "commit" || subcommand === "tag" ? ["-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false", ...args2] : args2;
18094
18112
  for (const command of windowsGitCandidates()) {
18095
- const result = child_process.spawnSync(command, hardenedArgs, {
18096
- cwd,
18097
- encoding: "utf-8",
18098
- timeout: GIT_TIMEOUT_MS,
18099
- windowsHide: true,
18100
- maxBuffer: GIT_MAX_BUFFER_BYTES,
18101
- stdio: ["ignore", "pipe", "pipe"],
18102
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
18103
- });
18104
- if (result.error) {
18105
- if (isGitBinaryMissing(result.error)) {
18106
- missingGitError ??= result.error;
18107
- continue;
18113
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
18114
+ const result = child_process.spawnSync(command, hardenedArgs, {
18115
+ cwd,
18116
+ encoding: "utf-8",
18117
+ timeout: GIT_TIMEOUT_MS,
18118
+ windowsHide: true,
18119
+ maxBuffer: GIT_MAX_BUFFER_BYTES,
18120
+ stdio: ["ignore", "pipe", "pipe"],
18121
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
18122
+ });
18123
+ if (!result.error && result.status === 0) {
18124
+ return result.stdout;
18125
+ }
18126
+ if (result.error) {
18127
+ if (isGitBinaryMissing(result.error)) {
18128
+ missingGitError ??= result.error;
18129
+ break;
18130
+ }
18131
+ if (isTransientSpawnError(result.error) && attempt < MAX_TRANSIENT_RETRIES - 1) {
18132
+ transientBackoff(attempt);
18133
+ continue;
18134
+ }
18135
+ throw new Error(errorMessage(result.error));
18136
+ }
18137
+ if (result.status !== 0) {
18138
+ throw new Error(result.stderr || result.stdout || `git exited with ${result.status}`);
18108
18139
  }
18109
- throw new Error(errorMessage(result.error));
18110
- }
18111
- if (result.status !== 0) {
18112
- throw new Error(result.stderr || result.stdout || `git exited with ${result.status}`);
18113
18140
  }
18114
- return result.stdout;
18115
18141
  }
18116
18142
  throw new GitBinaryMissingError(process.platform === "win32" ? "git executable is not available on PATH or common Windows install locations" : "git executable is not available on PATH", { cause: missingGitError });
18117
18143
  }
@@ -60605,20 +60631,31 @@ function writeCheckpointLog(log2, directory) {
60605
60631
  fs23.renameSync(tempPath, logPath);
60606
60632
  }
60607
60633
  function gitExec2(args2, cwd) {
60608
- const result = child_process3.spawnSync("git", args2, {
60609
- cwd,
60610
- encoding: "utf-8",
60611
- timeout: GIT_TIMEOUT_MS2,
60612
- stdio: ["ignore", "pipe", "pipe"],
60613
- windowsHide: true
60614
- });
60615
- if (result.error) {
60616
- throw new Error(`git failed to start: ${result.error.code ?? "unknown"} — ${result.error.message}`);
60617
- }
60618
- if (result.status !== 0) {
60634
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
60635
+ const result = child_process3.spawnSync("git", args2, {
60636
+ cwd,
60637
+ encoding: "utf-8",
60638
+ timeout: GIT_TIMEOUT_MS2,
60639
+ stdio: ["ignore", "pipe", "pipe"],
60640
+ windowsHide: true,
60641
+ maxBuffer: GIT_MAX_BUFFER_BYTES2
60642
+ });
60643
+ if (result.error) {
60644
+ const code = result.error.code;
60645
+ const message = result.error.message ?? "";
60646
+ const isTransient = isTransientSpawnError(result.error) || /ETIMEDOUT|timed out/i.test(message);
60647
+ if (!isTransient || attempt >= MAX_TRANSIENT_RETRIES - 1) {
60648
+ throw new Error(`git failed to start: ${code ?? "unknown"} — ${message}`);
60649
+ }
60650
+ transientBackoff(attempt);
60651
+ continue;
60652
+ }
60653
+ if (result.status === 0) {
60654
+ return result.stdout ?? "";
60655
+ }
60619
60656
  throw new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
60620
60657
  }
60621
- return result.stdout;
60658
+ throw new Error("git command failed after transient retries");
60622
60659
  }
60623
60660
  function appendRetentionEvent(directory, event) {
60624
60661
  try {
@@ -60635,9 +60672,20 @@ function getCurrentSha(directory) {
60635
60672
  function isGitRepo2(directory) {
60636
60673
  try {
60637
60674
  gitExec2(["rev-parse", "--git-dir"], directory);
60638
- return true;
60639
- } catch {
60640
- return false;
60675
+ return { isRepo: true };
60676
+ } catch (e) {
60677
+ const message = e instanceof Error ? e.message : String(e);
60678
+ const isTransient = /ETIMEDOUT|timed out/i.test(message) && !/not a git repository/i.test(message);
60679
+ if (isTransient) {
60680
+ return {
60681
+ isRepo: false,
60682
+ warning: "git probe failed after retry exhaustion — treating as not a git repository"
60683
+ };
60684
+ }
60685
+ return {
60686
+ isRepo: false,
60687
+ warning: "git probe failed — directory may not be a git repository"
60688
+ };
60641
60689
  }
60642
60690
  }
60643
60691
  function handleSave(label, directory) {
@@ -60718,7 +60766,8 @@ function saveCheckpointRecord(label, directory) {
60718
60766
  return { success: false, error: `duplicate label: "${label}"` };
60719
60767
  }
60720
60768
  let sha = "";
60721
- if (isGitRepo2(directory)) {
60769
+ const repoProbe = isGitRepo2(directory);
60770
+ if (repoProbe.isRepo) {
60722
60771
  try {
60723
60772
  sha = getCurrentSha(directory);
60724
60773
  } catch {
@@ -60731,7 +60780,14 @@ function saveCheckpointRecord(label, directory) {
60731
60780
  timestamp: new Date().toISOString()
60732
60781
  });
60733
60782
  writeCheckpointLog(log2, directory);
60734
- return { success: true, sha };
60783
+ const result = {
60784
+ success: true,
60785
+ sha
60786
+ };
60787
+ if (!sha) {
60788
+ result.warning = "no git restore target — checkpoint recorded without a SHA (directory may not be a git repository or HEAD is unavailable)";
60789
+ }
60790
+ return result;
60735
60791
  } catch (e) {
60736
60792
  return {
60737
60793
  success: false,
@@ -60805,11 +60861,12 @@ function handleDelete(label, directory) {
60805
60861
  }, null, 2);
60806
60862
  }
60807
60863
  }
60808
- var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json", MAX_LABEL_LENGTH = 100, GIT_TIMEOUT_MS2 = 30000, SHELL_METACHARACTERS, SAFE_LABEL_PATTERN, CONTROL_CHAR_PATTERN, NON_ASCII_PATTERN, checkpoint;
60864
+ var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json", MAX_LABEL_LENGTH = 100, GIT_TIMEOUT_MS2 = 30000, GIT_MAX_BUFFER_BYTES2, SHELL_METACHARACTERS, SAFE_LABEL_PATTERN, CONTROL_CHAR_PATTERN, NON_ASCII_PATTERN, checkpoint;
60809
60865
  var init_checkpoint = __esm(() => {
60810
60866
  init_zod();
60811
60867
  init_config();
60812
60868
  init_create_tool();
60869
+ GIT_MAX_BUFFER_BYTES2 = 5 * 1024 * 1024;
60813
60870
  SHELL_METACHARACTERS = /[;|&$`(){}<>!'"]/;
60814
60871
  SAFE_LABEL_PATTERN = /^[a-zA-Z0-9_ -]+$/;
60815
60872
  CONTROL_CHAR_PATTERN = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
@@ -60821,11 +60878,12 @@ var init_checkpoint = __esm(() => {
60821
60878
  label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
60822
60879
  },
60823
60880
  execute: async (args2, directory) => {
60824
- if (!isGitRepo2(directory)) {
60881
+ const repoProbe = isGitRepo2(directory);
60882
+ if (!repoProbe.isRepo) {
60825
60883
  return JSON.stringify({
60826
60884
  action: "unknown",
60827
60885
  success: false,
60828
- error: "not a git repository"
60886
+ error: `${repoProbe.warning ?? "not a git repository"} — checkpoint tools require a git repository`
60829
60887
  }, null, 2);
60830
60888
  }
60831
60889
  let action;
@@ -62914,7 +62972,8 @@ async function runCuratorPostMortem(directory, options = {}) {
62914
62972
  } catch {
62915
62973
  warnings.push("Failed to load plan data.");
62916
62974
  }
62917
- const reportFilename = `post-mortem-${planId}.md`;
62975
+ const effectivePlanId = planId === "unknown" ? `unknown-${Date.now()}` : planId;
62976
+ const reportFilename = `post-mortem-${effectivePlanId}.md`;
62918
62977
  let reportPath;
62919
62978
  try {
62920
62979
  reportPath = validateSwarmPath(directory, reportFilename);
@@ -62930,22 +62989,22 @@ async function runCuratorPostMortem(directory, options = {}) {
62930
62989
  if (!options.force && isReportValid(reportPath)) {
62931
62990
  return {
62932
62991
  success: true,
62933
- planId,
62992
+ planId: effectivePlanId,
62934
62993
  reportPath,
62935
62994
  summary: "Post-mortem report already exists (idempotent skip).",
62936
62995
  warnings
62937
62996
  };
62938
62997
  }
62939
- const lock = await _internals28.acquirePostMortemLock(directory, planId);
62998
+ const lock = await _internals28.acquirePostMortemLock(directory, effectivePlanId);
62940
62999
  if (!lock.acquired) {
62941
63000
  return {
62942
63001
  success: false,
62943
- planId,
63002
+ planId: effectivePlanId,
62944
63003
  reportPath,
62945
63004
  summary: null,
62946
63005
  warnings: [
62947
63006
  ...warnings,
62948
- `Concurrent post-mortem run in progress for plan ${planId}; skipped.`
63007
+ `Concurrent post-mortem run in progress for plan ${effectivePlanId}; skipped.`
62949
63008
  ]
62950
63009
  };
62951
63010
  }
@@ -62995,7 +63054,7 @@ async function runCuratorPostMortem(directory, options = {}) {
62995
63054
  if (options.llmDelegate) {
62996
63055
  try {
62997
63056
  const { CURATOR_POSTMORTEM_PROMPT: CURATOR_POSTMORTEM_PROMPT2 } = await Promise.resolve().then(() => exports_explorer);
62998
- const userInput = assembleLLMInput(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
63057
+ const userInput = assembleLLMInput(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
62999
63058
  const ac = new AbortController;
63000
63059
  const timer = setTimeout(() => ac.abort(), 300000);
63001
63060
  let llmOutput;
@@ -63011,17 +63070,17 @@ async function runCuratorPostMortem(directory, options = {}) {
63011
63070
  } finally {
63012
63071
  clearTimeout(timer);
63013
63072
  }
63014
- reportContent = `# Post-Mortem Report: ${planId}
63073
+ reportContent = `# Post-Mortem Report: ${effectivePlanId}
63015
63074
  Generated: ${new Date().toISOString()}
63016
63075
 
63017
63076
  ${llmOutput}`;
63018
63077
  } catch (err2) {
63019
63078
  const msg = err2 instanceof Error ? err2.message : String(err2);
63020
63079
  warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
63021
- reportContent = _internals28.buildDataOnlyReport(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
63080
+ reportContent = _internals28.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
63022
63081
  }
63023
63082
  } else {
63024
- reportContent = _internals28.buildDataOnlyReport(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
63083
+ reportContent = _internals28.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
63025
63084
  }
63026
63085
  try {
63027
63086
  const { mkdirSync: mkdirSync16 } = await import("node:fs");
@@ -63031,7 +63090,7 @@ ${llmOutput}`;
63031
63090
  const msg = err2 instanceof Error ? err2.message : String(err2);
63032
63091
  return {
63033
63092
  success: false,
63034
- planId,
63093
+ planId: effectivePlanId,
63035
63094
  reportPath: null,
63036
63095
  summary: null,
63037
63096
  warnings: [...warnings, `Failed to write report: ${msg}`]
@@ -63041,13 +63100,13 @@ ${llmOutput}`;
63041
63100
  const neverAppliedCount = knowledgeSummary.filter((e) => e.applied === 0 && e.violated === 0 && e.ignored === 0).length;
63042
63101
  const totalViolations = knowledgeSummary.reduce((s, e) => s + e.violated, 0);
63043
63102
  const summary = [
63044
- `Post-mortem for plan "${planId}": ${totalEntries} knowledge entries reviewed.`,
63103
+ `Post-mortem for plan "${effectivePlanId}": ${totalEntries} knowledge entries reviewed.`,
63045
63104
  `${neverAppliedCount} never-applied entries flagged; ${totalViolations} total violations recorded.`,
63046
63105
  `${proposals.length} pending proposals, ${unactionable.length} quarantined entries.`
63047
63106
  ].join(" ");
63048
63107
  return {
63049
63108
  success: true,
63050
- planId,
63109
+ planId: effectivePlanId,
63051
63110
  reportPath,
63052
63111
  summary,
63053
63112
  warnings
@@ -71751,6 +71810,7 @@ var init_write_retro = __esm(() => {
71751
71810
  });
71752
71811
 
71753
71812
  // src/commands/close.ts
71813
+ import { spawnSync as spawnSync9 } from "node:child_process";
71754
71814
  import * as fsSync6 from "node:fs";
71755
71815
  import { promises as fs28 } from "node:fs";
71756
71816
  import path58 from "node:path";
@@ -71790,8 +71850,9 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
71790
71850
  return Number.isFinite(createdAtMs) && createdAtMs >= sessionStartMs;
71791
71851
  }).length;
71792
71852
  }
71793
- async function copyDirRecursive(src, dest) {
71853
+ async function copyDirRecursiveWithFailures(src, dest) {
71794
71854
  let count = 0;
71855
+ const failures = [];
71795
71856
  const entries = await fs28.readdir(src);
71796
71857
  await fs28.mkdir(dest, { recursive: true });
71797
71858
  for (const entry of entries) {
@@ -71800,17 +71861,32 @@ async function copyDirRecursive(src, dest) {
71800
71861
  try {
71801
71862
  const stat9 = await fs28.stat(srcEntry);
71802
71863
  if (stat9.isDirectory()) {
71803
- const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
71804
- count += subCount;
71864
+ const subResult = await copyDirRecursiveWithFailures(srcEntry, destEntry);
71865
+ count += subResult.copied;
71866
+ failures.push(...subResult.failures);
71805
71867
  } else {
71806
71868
  try {
71807
71869
  await fs28.copyFile(srcEntry, destEntry);
71808
71870
  count++;
71809
- } catch {}
71871
+ } catch (err2) {
71872
+ const errno = err2?.code;
71873
+ if (errno !== "ENOENT") {
71874
+ failures.push(`${srcEntry}: ${err2 instanceof Error ? err2.message : String(err2)}`);
71875
+ }
71876
+ }
71810
71877
  }
71811
- } catch {}
71878
+ } catch (err2) {
71879
+ const errno = err2?.code;
71880
+ if (errno !== "ENOENT") {
71881
+ failures.push(`${srcEntry}: ${err2 instanceof Error ? err2.message : String(err2)}`);
71882
+ }
71883
+ }
71812
71884
  }
71813
- return count;
71885
+ return { copied: count, failures };
71886
+ }
71887
+ async function copyDirRecursive(src, dest) {
71888
+ const result = await copyDirRecursiveWithFailures(src, dest);
71889
+ return result.copied;
71814
71890
  }
71815
71891
  function guaranteeAllPlansComplete(planData) {
71816
71892
  const closedPhaseIds = [];
@@ -72082,31 +72158,145 @@ async function runFinalizeStage(ctx) {
72082
72158
  ctx.warnings.push(`Post-mortem failed: ${msg}`);
72083
72159
  }
72084
72160
  }
72161
+ async function copySqliteSafe(srcPath, destPath) {
72162
+ if (!fsSync6.existsSync(srcPath)) {
72163
+ return {
72164
+ success: true,
72165
+ skipped: true,
72166
+ reason: "source does not exist (ENOENT)"
72167
+ };
72168
+ }
72169
+ let checkpointVerified = false;
72170
+ try {
72171
+ const result = spawnSync9("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
72172
+ cwd: path58.dirname(srcPath),
72173
+ encoding: "utf-8",
72174
+ stdio: ["ignore", "pipe", "pipe"],
72175
+ timeout: 1e4,
72176
+ windowsHide: true,
72177
+ maxBuffer: 1024
72178
+ });
72179
+ if (result.error) {
72180
+ const code = result.error.code;
72181
+ if (code === "ENOENT") {
72182
+ try {
72183
+ await fs28.copyFile(srcPath, destPath);
72184
+ return {
72185
+ success: true,
72186
+ reason: "copied without WAL checkpoint (sqlite3 CLI unavailable)"
72187
+ };
72188
+ } catch (copyErr) {
72189
+ return {
72190
+ success: false,
72191
+ reason: `fallback copy failed: ${copyErr instanceof Error ? copyErr.message : String(copyErr)}`
72192
+ };
72193
+ }
72194
+ }
72195
+ return {
72196
+ success: false,
72197
+ reason: `wal_checkpoint failed: ${result.error instanceof Error ? result.error.message : String(result.error)}`
72198
+ };
72199
+ }
72200
+ if (result.status !== 0) {
72201
+ return {
72202
+ success: false,
72203
+ reason: `wal_checkpoint exited with code ${result.status}`
72204
+ };
72205
+ }
72206
+ const output = (result.stdout || "").trim();
72207
+ const lines = output.split(`
72208
+ `).filter((l) => l.trim());
72209
+ if (lines.length >= 1) {
72210
+ const dataLine = lines[0];
72211
+ const columns = dataLine.split("|");
72212
+ const busyFlag = parseInt(columns[0], 10);
72213
+ checkpointVerified = !Number.isNaN(busyFlag) && busyFlag === 0;
72214
+ }
72215
+ } catch (err2) {
72216
+ return {
72217
+ success: false,
72218
+ reason: `wal_checkpoint error: ${err2 instanceof Error ? err2.message : String(err2)}`
72219
+ };
72220
+ }
72221
+ try {
72222
+ await fs28.copyFile(srcPath, destPath);
72223
+ if (checkpointVerified) {
72224
+ return { success: true };
72225
+ }
72226
+ return {
72227
+ success: true,
72228
+ reason: "WAL checkpoint incomplete (busy) — archive copy may be stale, original preserved"
72229
+ };
72230
+ } catch (err2) {
72231
+ return {
72232
+ success: false,
72233
+ reason: `copy failed: ${err2 instanceof Error ? err2.message : String(err2)}`
72234
+ };
72235
+ }
72236
+ }
72085
72237
  async function runArchiveStage(ctx) {
72086
72238
  ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
72087
72239
  ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
72088
72240
  ctx.archiveDir = path58.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
72089
72241
  try {
72090
72242
  await fs28.mkdir(ctx.archiveDir, { recursive: true });
72243
+ const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
72091
72244
  for (const artifact of ARCHIVE_ARTIFACTS) {
72245
+ if (WAL_SIDECAR_FILES.has(artifact)) {
72246
+ continue;
72247
+ }
72092
72248
  const srcPath = path58.join(ctx.swarmDir, artifact);
72093
72249
  const destPath = path58.join(ctx.archiveDir, artifact);
72094
- try {
72095
- await fs28.copyFile(srcPath, destPath);
72096
- ctx.archivedFileCount++;
72097
- if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
72098
- ctx.archivedActiveStateFiles.add(artifact);
72250
+ if (artifact === "swarm.db") {
72251
+ const result = await copySqliteSafe(srcPath, destPath);
72252
+ if (result.skipped) {} else if (result.success) {
72253
+ ctx.archivedFileCount++;
72254
+ if (result.reason) {
72255
+ ctx.warnings.push(`Archived ${artifact}: ${result.reason}. Original preserved to prevent data loss.`);
72256
+ } else {
72257
+ ctx.archivedActiveStateFiles.add(artifact);
72258
+ }
72259
+ } else {
72260
+ ctx.archiveFailureReasons.set(artifact, result.reason);
72261
+ ctx.warnings.push(`Failed to archive ${artifact}: ${result.reason}. File preserved (not cleaned up).`);
72099
72262
  }
72100
- } catch {}
72263
+ } else {
72264
+ try {
72265
+ await fs28.copyFile(srcPath, destPath);
72266
+ ctx.archivedFileCount++;
72267
+ if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
72268
+ ctx.archivedActiveStateFiles.add(artifact);
72269
+ }
72270
+ } catch (err2) {
72271
+ const errno = err2?.code;
72272
+ if (errno === "ENOENT") {} else {
72273
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72274
+ ctx.archiveFailureReasons.set(artifact, `${errno ?? "unknown"}: ${reason}`);
72275
+ ctx.warnings.push(`Failed to archive ${artifact} [${errno ?? "unknown"}]: ${reason}. File preserved (not cleaned up).`);
72276
+ }
72277
+ }
72278
+ }
72101
72279
  }
72102
72280
  for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
72103
72281
  const srcDir = path58.join(ctx.swarmDir, dirName);
72104
72282
  const destDir = path58.join(ctx.archiveDir, dirName);
72105
72283
  try {
72106
- const copied = await copyDirRecursive(srcDir, destDir);
72107
- ctx.archivedFileCount += copied;
72108
- ctx.archivedActiveStateDirs.add(dirName);
72109
- } catch {}
72284
+ const result = await copyDirRecursiveWithFailures(srcDir, destDir);
72285
+ ctx.archivedFileCount += result.copied;
72286
+ if (result.failures.length === 0) {
72287
+ ctx.archivedActiveStateDirs.add(dirName);
72288
+ } else {
72289
+ ctx.warnings.push(`Directory ${dirName} not fully archived (${result.failures.length} failure(s)). Source preserved.`);
72290
+ for (const failure of result.failures) {
72291
+ ctx.warnings.push(` - ${failure}`);
72292
+ }
72293
+ }
72294
+ } catch (err2) {
72295
+ const code = err2.code;
72296
+ if (code !== "ENOENT") {
72297
+ ctx.warnings.push(`Failed to archive directory ${dirName} [${code ?? "unknown"}]: ${err2.message}. Source preserved.`);
72298
+ }
72299
+ }
72110
72300
  }
72111
72301
  ctx.archiveResult = `Archived ${ctx.archivedFileCount} artifact(s) to .swarm/archive/swarm-${ctx.timestamp}-${ctx.archiveSuffix}/`;
72112
72302
  } catch (archiveError) {
@@ -72147,14 +72337,21 @@ async function runCleanStage(ctx) {
72147
72337
  if (ctx.archivedActiveStateFiles.size > 0) {
72148
72338
  for (const artifact of ACTIVE_STATE_TO_CLEAN) {
72149
72339
  if (!ctx.archivedActiveStateFiles.has(artifact)) {
72150
- ctx.warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
72340
+ const reason = ctx.archiveFailureReasons?.get(artifact);
72341
+ ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
72151
72342
  continue;
72152
72343
  }
72153
72344
  const filePath = path58.join(ctx.swarmDir, artifact);
72154
72345
  try {
72155
72346
  await fs28.unlink(filePath);
72156
72347
  cleanedFiles.push(artifact);
72157
- } catch {}
72348
+ } catch (err2) {
72349
+ const errno = err2?.code;
72350
+ if (errno === "ENOENT") {} else {
72351
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72352
+ ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno ?? "unknown"}]: ${reason}`);
72353
+ }
72354
+ }
72158
72355
  }
72159
72356
  } else {
72160
72357
  ctx.warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
@@ -72176,15 +72373,33 @@ async function runCleanStage(ctx) {
72176
72373
  try {
72177
72374
  await fs28.unlink(path58.join(ctx.swarmDir, backup));
72178
72375
  configBackupsRemoved++;
72179
- } catch {}
72376
+ } catch (err2) {
72377
+ const errno = err2?.code;
72378
+ if (errno === "ENOENT") {} else {
72379
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72380
+ ctx.warnings.push(`Failed to clean config-backup ${backup} [${errno ?? "unknown"}]: ${reason}`);
72381
+ }
72382
+ }
72180
72383
  }
72181
72384
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
72182
72385
  for (const sibling of ledgerSiblings) {
72183
72386
  try {
72184
72387
  await fs28.unlink(path58.join(ctx.swarmDir, sibling));
72185
- } catch {}
72388
+ } catch (err2) {
72389
+ const errno = err2?.code;
72390
+ if (errno === "ENOENT") {} else {
72391
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72392
+ ctx.warnings.push(`Failed to clean ledger sibling ${sibling} [${errno ?? "unknown"}]: ${reason}`);
72393
+ }
72394
+ }
72186
72395
  }
72187
- } catch {}
72396
+ } catch (err2) {
72397
+ const errno = err2?.code;
72398
+ if (errno === "ENOENT") {} else {
72399
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72400
+ ctx.warnings.push(`Failed to read ${ctx.swarmDir} for stale-file cleanup [${errno ?? "unknown"}]: ${reason}`);
72401
+ }
72402
+ }
72188
72403
  let swarmPlanFilesRemoved = 0;
72189
72404
  const candidates = [
72190
72405
  path58.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
@@ -72210,9 +72425,21 @@ async function runCleanStage(ctx) {
72210
72425
  try {
72211
72426
  await fs28.unlink(path58.join(ctx.swarmDir, tmp));
72212
72427
  tmpFilesRemoved++;
72213
- } catch {}
72428
+ } catch (err2) {
72429
+ const errno = err2?.code;
72430
+ if (errno === "ENOENT") {} else {
72431
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72432
+ ctx.warnings.push(`Failed to clean tmp file ${tmp} [${errno ?? "unknown"}]: ${reason}`);
72433
+ }
72434
+ }
72214
72435
  }
72215
- } catch {}
72436
+ } catch (err2) {
72437
+ const errno = err2?.code;
72438
+ if (errno === "ENOENT") {} else {
72439
+ const reason = err2 instanceof Error ? err2.message : String(err2);
72440
+ ctx.warnings.push(`Failed to read ${ctx.swarmDir} for tmp-file cleanup [${errno ?? "unknown"}]: ${reason}`);
72441
+ }
72442
+ }
72216
72443
  if (tmpFilesRemoved > 0) {
72217
72444
  cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
72218
72445
  }
@@ -72229,9 +72456,14 @@ async function runCleanStage(ctx) {
72229
72456
  ""
72230
72457
  ].join(`
72231
72458
  `);
72459
+ const contextTempPath = path58.join(path58.dirname(contextPath), `${path58.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
72232
72460
  try {
72233
- await fs28.writeFile(contextPath, contextContent, "utf-8");
72461
+ await fs28.writeFile(contextTempPath, contextContent, "utf-8");
72462
+ fsSync6.renameSync(contextTempPath, contextPath);
72234
72463
  } catch (error93) {
72464
+ try {
72465
+ fsSync6.unlinkSync(contextTempPath);
72466
+ } catch {}
72235
72467
  const msg = error93 instanceof Error ? error93.message : String(error93);
72236
72468
  ctx.warnings.push(`Failed to reset context.md: ${msg}`);
72237
72469
  console.warn("[close-command] Failed to write context.md:", error93);
@@ -72325,15 +72557,33 @@ async function handleCloseCommand(directory, args2, options = {}) {
72325
72557
  if (!finalizeLock.acquired) {
72326
72558
  return `❌ Another /swarm finalize is already running for this project. If you are certain no other run is active, wait for the lock to expire or remove the stale lock and retry.`;
72327
72559
  }
72328
- const phases = planData.phases ?? [];
72329
- const inProgressPhases = phases.filter((p) => p.status === "in_progress");
72330
- const isForced = args2.includes("--force");
72331
- const runSkillReview = args2.includes("--skill-review");
72332
- let planAlreadyDone = false;
72333
- if (planExists) {
72334
- planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
72335
- }
72336
72560
  try {
72561
+ if (!planExists) {
72562
+ const archiveDir = path58.join(swarmDir, "archive");
72563
+ try {
72564
+ const archiveEntries = await fs28.readdir(archiveDir);
72565
+ const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
72566
+ if (hasArchiveBundle) {
72567
+ const hasActiveState = [
72568
+ ...ACTIVE_STATE_TO_CLEAN,
72569
+ ...ACTIVE_STATE_DIRS_TO_CLEAN
72570
+ ].some((entry) => fsSync6.existsSync(path58.join(swarmDir, entry)));
72571
+ if (!hasActiveState) {
72572
+ return `✅ Already finalized — nothing to do.
72573
+
72574
+ This project was already finalized in a previous /swarm close run. The plan has been archived and cleaned up. No further action is needed.`;
72575
+ }
72576
+ }
72577
+ } catch {}
72578
+ }
72579
+ const phases = planData.phases ?? [];
72580
+ const inProgressPhases = phases.filter((p) => p.status === "in_progress");
72581
+ const isForced = args2.includes("--force");
72582
+ const runSkillReview = args2.includes("--skill-review");
72583
+ let planAlreadyDone = false;
72584
+ if (planExists) {
72585
+ planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
72586
+ }
72337
72587
  const { config: loadedConfig } = _internals37.loadPluginConfigWithMeta(directory);
72338
72588
  const config3 = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
72339
72589
  const ctx = {
@@ -72370,6 +72620,7 @@ async function handleCloseCommand(directory, args2, options = {}) {
72370
72620
  archivedFileCount: 0,
72371
72621
  archivedActiveStateFiles: new Set,
72372
72622
  archivedActiveStateDirs: new Set,
72623
+ archiveFailureReasons: new Map,
72373
72624
  timestamp: "",
72374
72625
  archiveDir: "",
72375
72626
  archiveSuffix: "",
@@ -72432,9 +72683,14 @@ async function handleCloseCommand(directory, args2, options = {}) {
72432
72683
  ...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
72433
72684
  ].join(`
72434
72685
  `);
72686
+ const closeSummaryTempPath = path58.join(path58.dirname(closeSummaryPath), `${path58.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
72435
72687
  try {
72436
- await fs28.writeFile(closeSummaryPath, summaryContent, "utf-8");
72688
+ await fs28.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
72689
+ fsSync6.renameSync(closeSummaryTempPath, closeSummaryPath);
72437
72690
  } catch (error93) {
72691
+ try {
72692
+ fsSync6.unlinkSync(closeSummaryTempPath);
72693
+ } catch {}
72438
72694
  const msg = error93 instanceof Error ? error93.message : String(error93);
72439
72695
  ctx.warnings.push(`Failed to write close-summary.md: ${msg}`);
72440
72696
  console.warn("[close-command] Failed to write close-summary.md:", error93);
@@ -72877,7 +73133,7 @@ __export(exports_skill_consolidation, {
72877
73133
  consolidationStatePath: () => consolidationStatePath,
72878
73134
  _internals: () => _internals38
72879
73135
  });
72880
- import { existsSync as existsSync31 } from "node:fs";
73136
+ import { existsSync as existsSync32 } from "node:fs";
72881
73137
  import { mkdir as mkdir16, readFile as readFile16, rename as rename9, writeFile as writeFile14 } from "node:fs/promises";
72882
73138
  import * as path60 from "node:path";
72883
73139
  function consolidationStatePath(directory) {
@@ -72885,7 +73141,7 @@ function consolidationStatePath(directory) {
72885
73141
  }
72886
73142
  async function readState2(directory) {
72887
73143
  const filePath = consolidationStatePath(directory);
72888
- if (!existsSync31(filePath))
73144
+ if (!existsSync32(filePath))
72889
73145
  return {};
72890
73146
  try {
72891
73147
  const parsed = JSON.parse(await readFile16(filePath, "utf-8"));
@@ -74514,7 +74770,7 @@ var init_gate_bridge = __esm(() => {
74514
74770
  });
74515
74771
 
74516
74772
  // src/services/version-check.ts
74517
- import { existsSync as existsSync32, mkdirSync as mkdirSync20, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
74773
+ import { existsSync as existsSync33, mkdirSync as mkdirSync20, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
74518
74774
  import { homedir as homedir7 } from "node:os";
74519
74775
  import { join as join49 } from "node:path";
74520
74776
  function cacheDir() {
@@ -74528,7 +74784,7 @@ function cacheFile() {
74528
74784
  function readVersionCache() {
74529
74785
  try {
74530
74786
  const path65 = cacheFile();
74531
- if (!existsSync32(path65))
74787
+ if (!existsSync33(path65))
74532
74788
  return null;
74533
74789
  const raw = readFileSync17(path65, "utf-8");
74534
74790
  const parsed = JSON.parse(raw);
@@ -74626,10 +74882,10 @@ var init_version_check = __esm(() => {
74626
74882
  });
74627
74883
 
74628
74884
  // src/services/knowledge-diagnostics.ts
74629
- import { existsSync as existsSync33 } from "node:fs";
74885
+ import { existsSync as existsSync34 } from "node:fs";
74630
74886
  import { readFile as readFile18 } from "node:fs/promises";
74631
74887
  async function readRawLines(filePath) {
74632
- if (!existsSync33(filePath))
74888
+ if (!existsSync34(filePath))
74633
74889
  return { entries: [], corrupt: 0 };
74634
74890
  const content = await readFile18(filePath, "utf-8");
74635
74891
  const entries = [];
@@ -74754,7 +75010,7 @@ async function computeKnowledgeDebug(directory) {
74754
75010
  };
74755
75011
  }
74756
75012
  async function safeJsonlCount(filePath) {
74757
- if (!filePath || !existsSync33(filePath))
75013
+ if (!filePath || !existsSync34(filePath))
74758
75014
  return 0;
74759
75015
  try {
74760
75016
  const content = await readFile18(filePath, "utf-8");
@@ -74837,7 +75093,7 @@ var init_knowledge_diagnostics = __esm(() => {
74837
75093
 
74838
75094
  // src/services/diagnose-service.ts
74839
75095
  import * as child_process6 from "node:child_process";
74840
- import { existsSync as existsSync34, readdirSync as readdirSync7, readFileSync as readFileSync18, statSync as statSync11 } from "node:fs";
75096
+ import { existsSync as existsSync35, readdirSync as readdirSync7, readFileSync as readFileSync18, statSync as statSync11 } from "node:fs";
74841
75097
  import path65 from "node:path";
74842
75098
  import { fileURLToPath as fileURLToPath2 } from "node:url";
74843
75099
  function validateTaskDag(plan) {
@@ -75085,7 +75341,7 @@ async function checkConfigBackups(directory) {
75085
75341
  }
75086
75342
  async function checkGitRepository(directory) {
75087
75343
  try {
75088
- if (!existsSync34(directory) || !statSync11(directory).isDirectory()) {
75344
+ if (!existsSync35(directory) || !statSync11(directory).isDirectory()) {
75089
75345
  return {
75090
75346
  name: "Git Repository",
75091
75347
  status: "❌",
@@ -75150,7 +75406,7 @@ async function checkSpecStaleness(directory, plan) {
75150
75406
  }
75151
75407
  async function checkConfigParseability(directory) {
75152
75408
  const configPath = path65.join(directory, ".opencode/opencode-swarm.json");
75153
- if (!existsSync34(configPath)) {
75409
+ if (!existsSync35(configPath)) {
75154
75410
  return {
75155
75411
  name: "Config Parseability",
75156
75412
  status: "✅",
@@ -75205,11 +75461,11 @@ async function checkGrammarWasmFiles() {
75205
75461
  const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
75206
75462
  const grammarDir = resolveGrammarDir(thisDir);
75207
75463
  const missing = [];
75208
- if (!existsSync34(path65.join(grammarDir, "tree-sitter.wasm"))) {
75464
+ if (!existsSync35(path65.join(grammarDir, "tree-sitter.wasm"))) {
75209
75465
  missing.push("tree-sitter.wasm (core runtime)");
75210
75466
  }
75211
75467
  for (const file3 of grammarFiles) {
75212
- if (!existsSync34(path65.join(grammarDir, file3))) {
75468
+ if (!existsSync35(path65.join(grammarDir, file3))) {
75213
75469
  missing.push(file3);
75214
75470
  }
75215
75471
  }
@@ -75228,7 +75484,7 @@ async function checkGrammarWasmFiles() {
75228
75484
  }
75229
75485
  async function checkCheckpointManifest(directory) {
75230
75486
  const manifestPath = path65.join(directory, ".swarm/checkpoints.json");
75231
- if (!existsSync34(manifestPath)) {
75487
+ if (!existsSync35(manifestPath)) {
75232
75488
  return {
75233
75489
  name: "Checkpoint Manifest",
75234
75490
  status: "✅",
@@ -75280,7 +75536,7 @@ async function checkCheckpointManifest(directory) {
75280
75536
  }
75281
75537
  async function checkEventStreamIntegrity(directory) {
75282
75538
  const eventsPath = path65.join(directory, ".swarm/events.jsonl");
75283
- if (!existsSync34(eventsPath)) {
75539
+ if (!existsSync35(eventsPath)) {
75284
75540
  return {
75285
75541
  name: "Event Stream",
75286
75542
  status: "✅",
@@ -75321,7 +75577,7 @@ async function checkEventStreamIntegrity(directory) {
75321
75577
  }
75322
75578
  async function checkSteeringDirectives(directory) {
75323
75579
  const eventsPath = path65.join(directory, ".swarm/events.jsonl");
75324
- if (!existsSync34(eventsPath)) {
75580
+ if (!existsSync35(eventsPath)) {
75325
75581
  return {
75326
75582
  name: "Steering Directives",
75327
75583
  status: "✅",
@@ -75377,7 +75633,7 @@ async function checkCurator(directory) {
75377
75633
  };
75378
75634
  }
75379
75635
  const summaryPath = path65.join(directory, ".swarm/curator-summary.json");
75380
- if (!existsSync34(summaryPath)) {
75636
+ if (!existsSync35(summaryPath)) {
75381
75637
  return {
75382
75638
  name: "Curator",
75383
75639
  status: "✅",
@@ -75579,7 +75835,7 @@ async function getDiagnoseData(directory) {
75579
75835
  checks5.push(await checkKnowledgeHealth(directory));
75580
75836
  try {
75581
75837
  const evidenceDir = path65.join(directory, ".swarm", "evidence");
75582
- const snapshotFiles = existsSync34(evidenceDir) ? readdirSync7(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
75838
+ const snapshotFiles = existsSync35(evidenceDir) ? readdirSync7(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
75583
75839
  if (snapshotFiles.length > 0) {
75584
75840
  const latest = snapshotFiles.sort().pop();
75585
75841
  checks5.push({
@@ -75612,7 +75868,7 @@ async function getDiagnoseData(directory) {
75612
75868
  const cacheRows = [];
75613
75869
  for (const cachePath of cachePaths) {
75614
75870
  try {
75615
- if (!existsSync34(cachePath)) {
75871
+ if (!existsSync35(cachePath)) {
75616
75872
  cacheRows.push(`⬜ ${cachePath} — absent`);
75617
75873
  continue;
75618
75874
  }
@@ -80899,7 +81155,7 @@ var init_handoff_service = __esm(() => {
80899
81155
  });
80900
81156
 
80901
81157
  // src/session/snapshot-writer.ts
80902
- import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync26, openSync as openSync6, renameSync as renameSync15 } from "node:fs";
81158
+ import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync26, openSync as openSync6, renameSync as renameSync16 } from "node:fs";
80903
81159
  import * as path72 from "node:path";
80904
81160
  function serializeAgentSession(s) {
80905
81161
  const gateLog = {};
@@ -81018,7 +81274,7 @@ async function writeSnapshot(directory, state) {
81018
81274
  closeSync6(fd);
81019
81275
  }
81020
81276
  } catch {}
81021
- renameSync15(tempPath, resolvedPath);
81277
+ renameSync16(tempPath, resolvedPath);
81022
81278
  } catch (error93) {
81023
81279
  log("[snapshot-writer] write failed", {
81024
81280
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -81051,7 +81307,7 @@ var init_snapshot_writer = __esm(() => {
81051
81307
 
81052
81308
  // src/commands/handoff.ts
81053
81309
  import crypto7 from "node:crypto";
81054
- import { renameSync as renameSync16, unlinkSync as unlinkSync11 } from "node:fs";
81310
+ import { renameSync as renameSync17, unlinkSync as unlinkSync12 } from "node:fs";
81055
81311
  async function handleHandoffCommand(directory, _args) {
81056
81312
  const handoffData = await getHandoffData(directory);
81057
81313
  const markdown = formatHandoffMarkdown(handoffData);
@@ -81060,10 +81316,10 @@ async function handleHandoffCommand(directory, _args) {
81060
81316
  const tempPath = `${resolvedPath}.tmp.${crypto7.randomUUID()}`;
81061
81317
  await bunWrite(tempPath, markdown);
81062
81318
  try {
81063
- renameSync16(tempPath, resolvedPath);
81319
+ renameSync17(tempPath, resolvedPath);
81064
81320
  } catch (renameErr) {
81065
81321
  try {
81066
- unlinkSync11(tempPath);
81322
+ unlinkSync12(tempPath);
81067
81323
  } catch {}
81068
81324
  throw renameErr;
81069
81325
  }
@@ -81072,10 +81328,10 @@ async function handleHandoffCommand(directory, _args) {
81072
81328
  const promptTempPath = `${promptPath}.tmp.${crypto7.randomUUID()}`;
81073
81329
  await bunWrite(promptTempPath, continuationPrompt);
81074
81330
  try {
81075
- renameSync16(promptTempPath, promptPath);
81331
+ renameSync17(promptTempPath, promptPath);
81076
81332
  } catch (renameErr) {
81077
81333
  try {
81078
- unlinkSync11(promptTempPath);
81334
+ unlinkSync12(promptTempPath);
81079
81335
  } catch {}
81080
81336
  throw renameErr;
81081
81337
  }
@@ -81252,7 +81508,7 @@ var init_history = __esm(() => {
81252
81508
  });
81253
81509
 
81254
81510
  // src/commands/_shared/url-security.ts
81255
- import { spawnSync as spawnSync9 } from "node:child_process";
81511
+ import { spawnSync as spawnSync10 } from "node:child_process";
81256
81512
  function sanitizeUrl(raw) {
81257
81513
  let urlStr = raw.trim();
81258
81514
  urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
@@ -81417,7 +81673,7 @@ var init_url_security = __esm(() => {
81417
81673
  IPV4_ZERO_NETWORK = /^0\./;
81418
81674
  IPV6_LINK_LOCAL = /^fe80:/i;
81419
81675
  IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
81420
- _internals49 = { spawnSync: spawnSync9 };
81676
+ _internals49 = { spawnSync: spawnSync10 };
81421
81677
  });
81422
81678
 
81423
81679
  // src/commands/issue.ts
@@ -81546,7 +81802,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
81546
81802
 
81547
81803
  // src/hooks/knowledge-migrator.ts
81548
81804
  import { randomUUID as randomUUID6 } from "node:crypto";
81549
- import { existsSync as existsSync41, readFileSync as readFileSync25 } from "node:fs";
81805
+ import { existsSync as existsSync42, readFileSync as readFileSync25 } from "node:fs";
81550
81806
  import { mkdir as mkdir17, readFile as readFile19, writeFile as writeFile15 } from "node:fs/promises";
81551
81807
  import * as os14 from "node:os";
81552
81808
  import * as path73 from "node:path";
@@ -81563,7 +81819,7 @@ async function migrateContextToKnowledge(directory, config3) {
81563
81819
  const sentinelPath = path73.join(directory, ".swarm", ".knowledge-migrated");
81564
81820
  const contextPath = path73.join(directory, ".swarm", "context.md");
81565
81821
  const knowledgePath = resolveSwarmKnowledgePath(directory);
81566
- if (existsSync41(sentinelPath)) {
81822
+ if (existsSync42(sentinelPath)) {
81567
81823
  return {
81568
81824
  migrated: false,
81569
81825
  entriesMigrated: 0,
@@ -81572,7 +81828,7 @@ async function migrateContextToKnowledge(directory, config3) {
81572
81828
  skippedReason: "sentinel-exists"
81573
81829
  };
81574
81830
  }
81575
- if (!existsSync41(contextPath)) {
81831
+ if (!existsSync42(contextPath)) {
81576
81832
  return {
81577
81833
  migrated: false,
81578
81834
  entriesMigrated: 0,
@@ -81664,7 +81920,7 @@ async function migrateHiveKnowledgeLegacy(config3) {
81664
81920
  const legacyHivePath = _internals50.resolveLegacyHiveKnowledgePath();
81665
81921
  const canonicalHivePath = resolveHiveKnowledgePath();
81666
81922
  const sentinelPath = path73.join(path73.dirname(canonicalHivePath), ".hive-knowledge-migrated");
81667
- if (existsSync41(sentinelPath)) {
81923
+ if (existsSync42(sentinelPath)) {
81668
81924
  return {
81669
81925
  migrated: false,
81670
81926
  entriesMigrated: 0,
@@ -81673,7 +81929,7 @@ async function migrateHiveKnowledgeLegacy(config3) {
81673
81929
  skippedReason: "sentinel-exists"
81674
81930
  };
81675
81931
  }
81676
- if (!existsSync41(legacyHivePath)) {
81932
+ if (!existsSync42(legacyHivePath)) {
81677
81933
  return {
81678
81934
  migrated: false,
81679
81935
  entriesMigrated: 0,
@@ -81875,7 +82131,7 @@ function truncateLesson2(text) {
81875
82131
  }
81876
82132
  function inferProjectName(directory) {
81877
82133
  const packageJsonPath = path73.join(directory, "package.json");
81878
- if (existsSync41(packageJsonPath)) {
82134
+ if (existsSync42(packageJsonPath)) {
81879
82135
  try {
81880
82136
  const pkg = JSON.parse(readFileSync25(packageJsonPath, "utf-8"));
81881
82137
  if (pkg.name && typeof pkg.name === "string") {
@@ -82494,7 +82750,26 @@ var init_redaction = __esm(() => {
82494
82750
  },
82495
82751
  {
82496
82752
  type: "env_secret",
82497
- pattern: /\b(?:[A-Z0-9]+_)*(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
82753
+ pattern: /\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
82754
+ },
82755
+ { type: "gitlab_token", pattern: /\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g },
82756
+ { type: "slack_token", pattern: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
82757
+ {
82758
+ type: "jwt_token",
82759
+ pattern: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
82760
+ },
82761
+ {
82762
+ type: "aws_secret_access_key",
82763
+ pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[=:]\s*[A-Za-z0-9/+=]{40}\b/g
82764
+ },
82765
+ {
82766
+ type: "stripe_secret_key",
82767
+ pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g
82768
+ },
82769
+ { type: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
82770
+ {
82771
+ type: "openssh_private_key_block",
82772
+ pattern: /-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g
82498
82773
  }
82499
82774
  ];
82500
82775
  });
@@ -83012,7 +83287,7 @@ function normalizeMemoryAgentRole(agentRole) {
83012
83287
  if (base === "critic" || base === "critic_sounding_board" || base === "critic_drift_verifier" || base === "critic_hallucination_verifier" || base === "critic_architecture_supervisor") {
83013
83288
  return "security";
83014
83289
  }
83015
- if (base === "curator_init" || base === "curator_phase")
83290
+ if (base === "curator_init" || base === "curator_phase" || base === "curator_postmortem")
83016
83291
  return "curator";
83017
83292
  if (base === "docs")
83018
83293
  return "sme";
@@ -83202,7 +83477,7 @@ function scoreMemoryRecordDetailed(record3, request, context) {
83202
83477
  if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
83203
83478
  return { item: null, skipReason: "no_signal" };
83204
83479
  }
83205
- const score = textOverlap * 0.38 + tagOverlap * 0.16 + fileOverlap * 0.12 + symbolOverlap * 0.08 + taskTermOverlap * 0.08 + scopeSpecificityBoost(record3.scope) * 0.12 + kindProfileBoost(record3.kind, request) * 0.06 + roleBoost * 0.05 + record3.confidence * 0.08;
83480
+ const score = textOverlap * SCORING_WEIGHTS.textOverlap + tagOverlap * SCORING_WEIGHTS.tagOverlap + fileOverlap * SCORING_WEIGHTS.fileOverlap + symbolOverlap * SCORING_WEIGHTS.symbolOverlap + taskTermOverlap * SCORING_WEIGHTS.taskTermOverlap + scopeSpecificityBoost(record3.scope) * SCORING_WEIGHTS.scopeSpecificityBoost + kindProfileBoost(record3.kind, request) * SCORING_WEIGHTS.kindProfileBoost + roleBoost * SCORING_WEIGHTS.roleBoost + record3.confidence * SCORING_WEIGHTS.confidence;
83206
83481
  const reasonParts = [
83207
83482
  textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
83208
83483
  tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
@@ -83278,14 +83553,26 @@ function unionTokens(...sets) {
83278
83553
  }
83279
83554
  return union3;
83280
83555
  }
83556
+ var SCORING_WEIGHTS;
83281
83557
  var init_scoring = __esm(() => {
83282
83558
  init_role_profiles();
83283
83559
  init_schema2();
83560
+ SCORING_WEIGHTS = {
83561
+ textOverlap: 0.38,
83562
+ tagOverlap: 0.16,
83563
+ fileOverlap: 0.12,
83564
+ symbolOverlap: 0.08,
83565
+ taskTermOverlap: 0.08,
83566
+ scopeSpecificityBoost: 0.12,
83567
+ kindProfileBoost: 0.06,
83568
+ roleBoost: 0.05,
83569
+ confidence: 0.08
83570
+ };
83284
83571
  });
83285
83572
 
83286
83573
  // src/memory/local-jsonl-provider.ts
83287
83574
  import { randomUUID as randomUUID7 } from "node:crypto";
83288
- import { existsSync as existsSync42 } from "node:fs";
83575
+ import { existsSync as existsSync43 } from "node:fs";
83289
83576
  import {
83290
83577
  appendFile as appendFile9,
83291
83578
  mkdir as mkdir18,
@@ -83636,7 +83923,7 @@ function validateLoadedProposals(values, config3) {
83636
83923
  return { records, invalidCount };
83637
83924
  }
83638
83925
  async function readJsonl(filePath) {
83639
- if (!existsSync42(filePath))
83926
+ if (!existsSync43(filePath))
83640
83927
  return [];
83641
83928
  const content = await readFile20(filePath, "utf-8");
83642
83929
  const records = [];
@@ -83796,7 +84083,7 @@ var init_prompt_block = __esm(() => {
83796
84083
  });
83797
84084
 
83798
84085
  // src/memory/jsonl-migration.ts
83799
- import { existsSync as existsSync43 } from "node:fs";
84086
+ import { existsSync as existsSync44, renameSync as renameSync18, unlinkSync as unlinkSync13 } from "node:fs";
83800
84087
  import { copyFile as copyFile2, mkdir as mkdir19, readFile as readFile21, stat as stat10, writeFile as writeFile17 } from "node:fs/promises";
83801
84088
  import * as path75 from "node:path";
83802
84089
  function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
@@ -83828,10 +84115,10 @@ async function backupLegacyJsonl(rootDirectory, config3 = {}) {
83828
84115
  const results = [];
83829
84116
  for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
83830
84117
  const source = path75.join(storageDir, filename);
83831
- if (!existsSync43(source))
84118
+ if (!existsSync44(source))
83832
84119
  continue;
83833
84120
  const backup = path75.join(backupDir, `${filename}.pre-sqlite-migration`);
83834
- if (existsSync43(backup)) {
84121
+ if (existsSync44(backup)) {
83835
84122
  results.push({ source, backup, created: false });
83836
84123
  continue;
83837
84124
  }
@@ -83845,20 +84132,47 @@ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
83845
84132
  await mkdir19(exportDir, { recursive: true });
83846
84133
  const memoriesPath = path75.join(exportDir, "memories.jsonl");
83847
84134
  const proposalsPath = path75.join(exportDir, "proposals.jsonl");
83848
- await writeFile17(memoriesPath, toJsonl(memories), "utf-8");
83849
- await writeFile17(proposalsPath, toJsonl(proposals), "utf-8");
84135
+ const memoriesTempPath = path75.join(path75.dirname(memoriesPath), `${path75.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
84136
+ try {
84137
+ await writeFile17(memoriesTempPath, toJsonl(memories), "utf-8");
84138
+ renameSync18(memoriesTempPath, memoriesPath);
84139
+ } catch (err2) {
84140
+ try {
84141
+ unlinkSync13(memoriesTempPath);
84142
+ } catch {}
84143
+ throw err2;
84144
+ }
84145
+ const proposalsTempPath = path75.join(path75.dirname(proposalsPath), `${path75.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
84146
+ try {
84147
+ await writeFile17(proposalsTempPath, toJsonl(proposals), "utf-8");
84148
+ renameSync18(proposalsTempPath, proposalsPath);
84149
+ } catch (err2) {
84150
+ try {
84151
+ unlinkSync13(proposalsTempPath);
84152
+ } catch {}
84153
+ throw err2;
84154
+ }
83850
84155
  return { directory: exportDir, memoriesPath, proposalsPath };
83851
84156
  }
83852
84157
  async function writeMigrationReport(rootDirectory, report, config3 = {}) {
83853
84158
  const reportPath = path75.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
83854
84159
  await mkdir19(path75.dirname(reportPath), { recursive: true });
83855
- await writeFile17(reportPath, `${JSON.stringify(report, null, 2)}
84160
+ const reportTempPath = path75.join(path75.dirname(reportPath), `${path75.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
84161
+ try {
84162
+ await writeFile17(reportTempPath, `${JSON.stringify(report, null, 2)}
83856
84163
  `, "utf-8");
84164
+ renameSync18(reportTempPath, reportPath);
84165
+ } catch (err2) {
84166
+ try {
84167
+ unlinkSync13(reportTempPath);
84168
+ } catch {}
84169
+ throw err2;
84170
+ }
83857
84171
  return reportPath;
83858
84172
  }
83859
84173
  async function readMigrationReport(rootDirectory, config3 = {}) {
83860
84174
  const reportPath = path75.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
83861
- if (!existsSync43(reportPath))
84175
+ if (!existsSync44(reportPath))
83862
84176
  return null;
83863
84177
  try {
83864
84178
  return JSON.parse(await readFile21(reportPath, "utf-8"));
@@ -83872,13 +84186,13 @@ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
83872
84186
  for (const file3 of ["memories.jsonl", "proposals.jsonl"]) {
83873
84187
  const filePath = path75.join(storageDir, file3);
83874
84188
  let sizeBytes = 0;
83875
- if (existsSync43(filePath)) {
84189
+ if (existsSync44(filePath)) {
83876
84190
  sizeBytes = (await stat10(filePath)).size;
83877
84191
  }
83878
84192
  statuses.push({
83879
84193
  file: file3,
83880
84194
  path: filePath,
83881
- exists: existsSync43(filePath),
84195
+ exists: existsSync44(filePath),
83882
84196
  sizeBytes
83883
84197
  });
83884
84198
  }
@@ -83959,7 +84273,7 @@ async function readProposalJsonl(filePath, config3) {
83959
84273
  return { records, invalidRows, totalRows: rows.totalRows };
83960
84274
  }
83961
84275
  async function readJsonlRows(filePath) {
83962
- if (!existsSync43(filePath)) {
84276
+ if (!existsSync44(filePath)) {
83963
84277
  return { rows: [], invalidRows: [], totalRows: 0 };
83964
84278
  }
83965
84279
  const content = await readFile21(filePath, "utf-8");
@@ -84013,6 +84327,7 @@ class SQLiteMemoryProvider {
84013
84327
  rootDirectory;
84014
84328
  config;
84015
84329
  initialized = false;
84330
+ initPromise = null;
84016
84331
  db = null;
84017
84332
  ftsAvailable = false;
84018
84333
  memories = new Map;
@@ -84056,6 +84371,15 @@ class SQLiteMemoryProvider {
84056
84371
  async initialize() {
84057
84372
  if (this.initialized)
84058
84373
  return;
84374
+ if (!this.initPromise) {
84375
+ this.initPromise = this.doInitialize().catch((err2) => {
84376
+ this.initPromise = null;
84377
+ throw err2;
84378
+ });
84379
+ }
84380
+ return this.initPromise;
84381
+ }
84382
+ async doInitialize() {
84059
84383
  const dbPath = this.databasePath();
84060
84384
  mkdirSync27(path76.dirname(dbPath), { recursive: true });
84061
84385
  const Db = loadDatabaseCtor2();
@@ -84251,6 +84575,7 @@ class SQLiteMemoryProvider {
84251
84575
  this.db = null;
84252
84576
  this.ftsAvailable = false;
84253
84577
  this.initialized = false;
84578
+ this.initPromise = null;
84254
84579
  this.lastAutomaticJsonlMigration = null;
84255
84580
  }
84256
84581
  async importJsonl() {
@@ -84387,8 +84712,6 @@ class SQLiteMemoryProvider {
84387
84712
  try {
84388
84713
  if (!this.hasMigration(FTS_SCHEMA_MIGRATION_NAME)) {
84389
84714
  this.recreateFtsIndex();
84390
- this.markMigration(FTS_SCHEMA_MIGRATION_VERSION, FTS_SCHEMA_MIGRATION_NAME);
84391
- this.insertEvent("migration", String(FTS_SCHEMA_MIGRATION_VERSION), FTS_SCHEMA_MIGRATION_NAME);
84392
84715
  } else {
84393
84716
  db.run(`CREATE VIRTUAL TABLE IF NOT EXISTS ${FTS_TABLE_NAME} USING fts5(
84394
84717
  ${ftsCreateColumnsSql()}
@@ -84721,12 +85044,60 @@ class SQLiteMemoryProvider {
84721
85044
  }
84722
85045
  requireDb() {
84723
85046
  if (!this.db)
84724
- throw new Error("SQLite memory provider is not initialized");
85047
+ throw new MemoryValidationError("SQLite memory provider is not initialized", "provider_not_initialized");
84725
85048
  return this.db;
84726
85049
  }
84727
85050
  }
84728
85051
  function splitSql(sql) {
84729
- return sql.split(";").map((statement) => statement.trim()).filter(Boolean);
85052
+ const statements = [];
85053
+ let current = "";
85054
+ let inSingleQuote = false;
85055
+ let inLineComment = false;
85056
+ for (let i2 = 0;i2 < sql.length; i2++) {
85057
+ const char = sql[i2];
85058
+ const next = sql[i2 + 1];
85059
+ if (inLineComment) {
85060
+ if (char === `
85061
+ `) {
85062
+ inLineComment = false;
85063
+ }
85064
+ continue;
85065
+ }
85066
+ if (inSingleQuote) {
85067
+ if (char === "'" && next === "'") {
85068
+ current += "''";
85069
+ i2++;
85070
+ continue;
85071
+ }
85072
+ current += char;
85073
+ if (char === "'") {
85074
+ inSingleQuote = false;
85075
+ }
85076
+ continue;
85077
+ }
85078
+ if (char === "-" && next === "-") {
85079
+ inLineComment = true;
85080
+ i2++;
85081
+ continue;
85082
+ }
85083
+ if (char === "'") {
85084
+ inSingleQuote = true;
85085
+ current += char;
85086
+ continue;
85087
+ }
85088
+ if (char === ";") {
85089
+ const trimmed2 = current.trim();
85090
+ if (trimmed2)
85091
+ statements.push(trimmed2);
85092
+ current = "";
85093
+ continue;
85094
+ }
85095
+ current += char;
85096
+ }
85097
+ const trimmed = current.trim();
85098
+ if (trimmed)
85099
+ statements.push(trimmed);
85100
+ return statements;
84730
85101
  }
84731
85102
  function buildFtsQuery(request) {
84732
85103
  const text = request.mode === "injection" && request.task ? `${request.task}
@@ -84790,7 +85161,7 @@ function rerankWithFts(items, ftsOrder) {
84790
85161
  };
84791
85162
  }).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
84792
85163
  }
84793
- var _DatabaseCtor2 = null, FTS_SCHEMA_MIGRATION_VERSION = 3, FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index", FTS_TABLE_NAME = "memory_items_fts", FTS_INDEX_COLUMNS, FTS_INSERT_COLUMNS, MIGRATIONS2, FTS_STOP_WORDS;
85164
+ var _DatabaseCtor2 = null, FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index", FTS_TABLE_NAME = "memory_items_fts", FTS_INDEX_COLUMNS, FTS_INSERT_COLUMNS, MIGRATIONS2, FTS_STOP_WORDS;
84794
85165
  var init_sqlite_provider = __esm(() => {
84795
85166
  init_utils2();
84796
85167
  init_config3();
@@ -84886,6 +85257,15 @@ var init_sqlite_provider = __esm(() => {
84886
85257
  CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_bundle
84887
85258
  ON memory_recall_usage(bundle_id);
84888
85259
  `
85260
+ },
85261
+ {
85262
+ version: 3,
85263
+ name: "create_memory_fts5_shadow_index",
85264
+ sql: `
85265
+ CREATE VIRTUAL TABLE IF NOT EXISTS ${FTS_TABLE_NAME} USING fts5(
85266
+ ${ftsCreateColumnsSql()}
85267
+ );
85268
+ `
84889
85269
  }
84890
85270
  ];
84891
85271
  FTS_STOP_WORDS = new Set([
@@ -84923,7 +85303,7 @@ var init_sqlite_provider = __esm(() => {
84923
85303
 
84924
85304
  // src/memory/gateway.ts
84925
85305
  import { createHash as createHash12 } from "node:crypto";
84926
- import { existsSync as existsSync44, readFileSync as readFileSync26 } from "node:fs";
85306
+ import { existsSync as existsSync45, readFileSync as readFileSync26 } from "node:fs";
84927
85307
  import * as path77 from "node:path";
84928
85308
 
84929
85309
  class MemoryGateway {
@@ -85248,7 +85628,7 @@ function readGitRemoteUrl(directory) {
85248
85628
  if (gitRemoteUrlCache.has(directory))
85249
85629
  return gitRemoteUrlCache.get(directory);
85250
85630
  const gitConfigPath = path77.join(directory, ".git", "config");
85251
- if (!existsSync44(gitConfigPath)) {
85631
+ if (!existsSync45(gitConfigPath)) {
85252
85632
  gitRemoteUrlCache.set(directory, undefined);
85253
85633
  return;
85254
85634
  }
@@ -86036,65 +86416,69 @@ async function recallForAgent(input) {
86036
86416
  agentId: input.agentId,
86037
86417
  runId: input.sessionID
86038
86418
  }, { config: input.config });
86039
- const resolvedConfig = resolveMemoryConfig(input.config);
86040
- if (!gateway.isEnabled()) {
86041
- await logInjectionSkipped(input, "disabled");
86042
- return null;
86043
- }
86044
- if (!resolvedConfig.recall.injection.enabled) {
86045
- await logInjectionSkipped(input, "disabled");
86046
- return null;
86047
- }
86048
- const scopes = gateway.deriveAllowedScopes();
86049
- const planInput = {
86050
- userGoal: compactText(input.userGoal),
86051
- runId: input.sessionID ?? "unknown",
86052
- agentRole: input.agentRole,
86053
- agentId: input.agentId,
86054
- agentTask: compactText(input.agentTask),
86055
- touchedFiles: extractTouchedFiles(input.agentTask)
86056
- };
86057
- const plan = buildMemoryRecallPlan(planInput, { scopes });
86058
- plan.maxItems = resolvedConfig.recall.injection.maxItems;
86059
- plan.tokenBudget = resolvedConfig.recall.injection.tokenBudget;
86060
- await input.appendRunLog(input.directory, input.sessionID, {
86061
- event: "recall_requested",
86062
- runId: input.sessionID ?? "unknown",
86063
- agentRole: input.agentRole,
86064
- agentId: input.agentId,
86065
- metadata: {
86419
+ try {
86420
+ const resolvedConfig = resolveMemoryConfig(input.config);
86421
+ if (!gateway.isEnabled()) {
86422
+ await logInjectionSkipped(input, "disabled");
86423
+ return null;
86424
+ }
86425
+ if (!resolvedConfig.recall.injection.enabled) {
86426
+ await logInjectionSkipped(input, "disabled");
86427
+ return null;
86428
+ }
86429
+ const scopes = gateway.deriveAllowedScopes();
86430
+ const planInput = {
86431
+ userGoal: compactText(input.userGoal),
86432
+ runId: input.sessionID ?? "unknown",
86433
+ agentRole: input.agentRole,
86434
+ agentId: input.agentId,
86435
+ agentTask: compactText(input.agentTask),
86436
+ touchedFiles: extractTouchedFiles(input.agentTask)
86437
+ };
86438
+ const plan = buildMemoryRecallPlan(planInput, { scopes });
86439
+ plan.maxItems = resolvedConfig.recall.injection.maxItems;
86440
+ plan.tokenBudget = resolvedConfig.recall.injection.tokenBudget;
86441
+ await input.appendRunLog(input.directory, input.sessionID, {
86442
+ event: "recall_requested",
86443
+ runId: input.sessionID ?? "unknown",
86444
+ agentRole: input.agentRole,
86445
+ agentId: input.agentId,
86446
+ metadata: {
86447
+ kinds: plan.kinds,
86448
+ maxItems: plan.maxItems,
86449
+ tokenBudget: plan.tokenBudget,
86450
+ scopeTypes: plan.scopes.map((scope) => scope.type)
86451
+ }
86452
+ });
86453
+ const recallInput = {
86454
+ query: plan.query,
86455
+ task: planInput.agentTask,
86456
+ mode: "injection",
86457
+ scopes: plan.scopes,
86066
86458
  kinds: plan.kinds,
86067
86459
  maxItems: plan.maxItems,
86068
86460
  tokenBudget: plan.tokenBudget,
86069
- scopeTypes: plan.scopes.map((scope) => scope.type)
86461
+ minScore: resolvedConfig.recall.injection.minScore,
86462
+ requireQuerySignal: resolvedConfig.recall.injection.requireQuerySignal
86463
+ };
86464
+ const bundle = await gateway.recall(recallInput);
86465
+ await input.appendRunLog(input.directory, input.sessionID, {
86466
+ event: "recall_returned",
86467
+ runId: input.sessionID ?? "unknown",
86468
+ agentRole: input.agentRole,
86469
+ agentId: input.agentId,
86470
+ bundleId: bundle.id,
86471
+ memoryIds: bundle.items.map((item) => item.record.id),
86472
+ scores: bundle.items.map((item) => item.score),
86473
+ tokenEstimate: bundle.tokenEstimate
86474
+ });
86475
+ if (bundle.items.length === 0) {
86476
+ await logInjectionSkipped(input, bundle.diagnostics?.injectionSkipReason ?? "no_results", bundle);
86070
86477
  }
86071
- });
86072
- const recallInput = {
86073
- query: plan.query,
86074
- task: planInput.agentTask,
86075
- mode: "injection",
86076
- scopes: plan.scopes,
86077
- kinds: plan.kinds,
86078
- maxItems: plan.maxItems,
86079
- tokenBudget: plan.tokenBudget,
86080
- minScore: resolvedConfig.recall.injection.minScore,
86081
- requireQuerySignal: resolvedConfig.recall.injection.requireQuerySignal
86082
- };
86083
- const bundle = await gateway.recall(recallInput);
86084
- await input.appendRunLog(input.directory, input.sessionID, {
86085
- event: "recall_returned",
86086
- runId: input.sessionID ?? "unknown",
86087
- agentRole: input.agentRole,
86088
- agentId: input.agentId,
86089
- bundleId: bundle.id,
86090
- memoryIds: bundle.items.map((item) => item.record.id),
86091
- scores: bundle.items.map((item) => item.score),
86092
- tokenEstimate: bundle.tokenEstimate
86093
- });
86094
- if (bundle.items.length === 0) {
86095
- await logInjectionSkipped(input, bundle.diagnostics?.injectionSkipReason ?? "no_results", bundle);
86478
+ return { bundle, scopes };
86479
+ } finally {
86480
+ await gateway.dispose?.();
86096
86481
  }
86097
- return { bundle, scopes };
86098
86482
  }
86099
86483
  async function logInjectionSkipped(input, reason, bundle) {
86100
86484
  await input.appendRunLog(input.directory, input.sessionID, {
@@ -86136,7 +86520,7 @@ function parseTaskToolInput(input) {
86136
86520
  };
86137
86521
  }
86138
86522
  function isCuratorAgent(agentRole) {
86139
- return agentRole === "curator" || agentRole === "curator_init" || agentRole === "curator_phase";
86523
+ return agentRole === "curator" || agentRole === "curator_init" || agentRole === "curator_phase" || agentRole === "curator_postmortem";
86140
86524
  }
86141
86525
  function messagesContainRecall(messages) {
86142
86526
  return messages.some((message) => message?.parts?.some((part) => typeof part?.text === "string" && (part.text.includes(MEMORY_SENTINEL) || part.text.includes("Retrieved Swarm Memory"))));
@@ -86224,7 +86608,7 @@ var init_memory = __esm(() => {
86224
86608
  });
86225
86609
 
86226
86610
  // src/commands/memory.ts
86227
- import { existsSync as existsSync45 } from "node:fs";
86611
+ import { existsSync as existsSync46 } from "node:fs";
86228
86612
  import * as path80 from "node:path";
86229
86613
  import { fileURLToPath as fileURLToPath3 } from "node:url";
86230
86614
  async function handleMemoryCommand(_directory, _args) {
@@ -86256,7 +86640,7 @@ async function handleMemoryStatusCommand(directory, _args) {
86256
86640
  `- Provider: \`${config3.provider}\``,
86257
86641
  `- Storage: \`${storageDir}\``,
86258
86642
  `- SQLite path: \`${sqlitePath}\``,
86259
- `- SQLite database exists: \`${existsSync45(sqlitePath)}\``,
86643
+ `- SQLite database exists: \`${existsSync46(sqlitePath)}\``,
86260
86644
  `- Automatic destructive cleanup: \`disabled\``,
86261
86645
  "",
86262
86646
  "### Legacy JSONL"
@@ -86509,7 +86893,16 @@ function parseEvaluateArgs(directory, args2) {
86509
86893
  error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
86510
86894
  };
86511
86895
  }
86512
- fixtureDirectory = path80.resolve(directory, next);
86896
+ const resolvedFixtures = path80.resolve(directory, next);
86897
+ const canonical = path80.normalize(resolvedFixtures) + path80.sep;
86898
+ const allowedRootA = path80.normalize(directory) + path80.sep;
86899
+ const allowedRootB = path80.normalize(path80.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path80.sep;
86900
+ if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
86901
+ return {
86902
+ error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
86903
+ };
86904
+ }
86905
+ fixtureDirectory = resolvedFixtures;
86513
86906
  i2++;
86514
86907
  continue;
86515
86908
  }
@@ -91094,19 +91487,19 @@ function hasCompoundTestExtension(filename) {
91094
91487
  const lower = filename.toLowerCase();
91095
91488
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
91096
91489
  }
91097
- function isLanguageSpecificTestFile(basename12) {
91098
- const lower = basename12.toLowerCase();
91490
+ function isLanguageSpecificTestFile(basename13) {
91491
+ const lower = basename13.toLowerCase();
91099
91492
  if (lower.endsWith("_test.go"))
91100
91493
  return true;
91101
91494
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
91102
91495
  return true;
91103
91496
  if (lower.endsWith("_spec.rb"))
91104
91497
  return true;
91105
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename12) || basename12.endsWith("Test.java") || basename12.endsWith("Tests.java") || lower.endsWith("it.java")))
91498
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename13) || basename13.endsWith("Test.java") || basename13.endsWith("Tests.java") || lower.endsWith("it.java")))
91106
91499
  return true;
91107
91500
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
91108
91501
  return true;
91109
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename12) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
91502
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename13) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
91110
91503
  return true;
91111
91504
  if (lower.endsWith(".tests.ps1"))
91112
91505
  return true;
@@ -91114,23 +91507,23 @@ function isLanguageSpecificTestFile(basename12) {
91114
91507
  }
91115
91508
  function isConventionTestFilePath(filePath) {
91116
91509
  const normalizedPath = filePath.replace(/\\/g, "/");
91117
- const basename12 = path93.basename(filePath);
91118
- return hasCompoundTestExtension(basename12) || basename12.includes(".spec.") || basename12.includes(".test.") || isLanguageSpecificTestFile(basename12) || isTestDirectoryPath(normalizedPath);
91510
+ const basename13 = path93.basename(filePath);
91511
+ return hasCompoundTestExtension(basename13) || basename13.includes(".spec.") || basename13.includes(".test.") || isLanguageSpecificTestFile(basename13) || isTestDirectoryPath(normalizedPath);
91119
91512
  }
91120
91513
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
91121
91514
  const testFiles = [];
91122
91515
  for (const file3 of sourceFiles) {
91123
91516
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
91124
91517
  const relativeFile = path93.relative(workingDir, absoluteFile);
91125
- const basename12 = path93.basename(absoluteFile);
91518
+ const basename13 = path93.basename(absoluteFile);
91126
91519
  const dirname43 = path93.dirname(absoluteFile);
91127
91520
  const preferRelativeOutput = !path93.isAbsolute(file3);
91128
91521
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
91129
91522
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
91130
91523
  continue;
91131
91524
  }
91132
- const nameWithoutExt = basename12.replace(/\.[^.]+$/, "");
91133
- const ext = path93.extname(basename12);
91525
+ const nameWithoutExt = basename13.replace(/\.[^.]+$/, "");
91526
+ const ext = path93.extname(basename13);
91134
91527
  const genericTestNames = [
91135
91528
  `${nameWithoutExt}.spec${ext}`,
91136
91529
  `${nameWithoutExt}.test${ext}`
@@ -91141,7 +91534,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
91141
91534
  ...languageSpecificTestNames
91142
91535
  ].map((candidateName) => path93.join(dirname43, candidateName));
91143
91536
  const testDirectoryNames = [
91144
- basename12,
91537
+ basename13,
91145
91538
  ...genericTestNames,
91146
91539
  ...languageSpecificTestNames
91147
91540
  ];
@@ -94085,7 +94478,9 @@ async function handleResetCommand(directory, args2) {
94085
94478
  fs51.unlinkSync(rootPath);
94086
94479
  results.push(`- ✅ Deleted ${filename} (root)`);
94087
94480
  }
94088
- } catch {}
94481
+ } catch (err2) {
94482
+ results.push(`- ❌ Failed to delete ${filename}: ${err2 instanceof Error ? err2.message : String(err2)}`);
94483
+ }
94089
94484
  }
94090
94485
  try {
94091
94486
  resetAutomationManager();
@@ -95105,6 +95500,11 @@ var init_prm = __esm(() => {
95105
95500
  // src/commands/reset-session.ts
95106
95501
  import * as fs54 from "node:fs";
95107
95502
  import * as path98 from "node:path";
95503
+ function errorMessage2(err2) {
95504
+ if (err2 instanceof Error)
95505
+ return err2.message;
95506
+ return String(err2);
95507
+ }
95108
95508
  async function handleResetSessionCommand(directory, _args) {
95109
95509
  const results = [];
95110
95510
  try {
@@ -95118,22 +95518,30 @@ async function handleResetSessionCommand(directory, _args) {
95118
95518
  } catch {
95119
95519
  results.push("❌ Failed to delete state.json");
95120
95520
  }
95121
- try {
95122
- const sessionDir = path98.dirname(validateSwarmPath(directory, "session/state.json"));
95123
- if (fs54.existsSync(sessionDir)) {
95124
- const files = fs54.readdirSync(sessionDir);
95125
- const otherFiles = files.filter((f) => f !== "state.json");
95126
- let deletedCount = 0;
95127
- for (const file3 of otherFiles) {
95128
- const filePath = path98.join(sessionDir, file3);
95129
- if (fs54.lstatSync(filePath).isFile()) {
95130
- fs54.unlinkSync(filePath);
95131
- deletedCount++;
95132
- }
95133
- }
95134
- results.push(`✅ Cleaned ${deletedCount} additional session file(s)`);
95521
+ const sessionDir = path98.dirname(validateSwarmPath(directory, "session/state.json"));
95522
+ let sessionFiles = [];
95523
+ if (fs54.existsSync(sessionDir)) {
95524
+ try {
95525
+ sessionFiles = fs54.readdirSync(sessionDir);
95526
+ } catch (err2) {
95527
+ results.push(`❌ Failed to read session directory: ${errorMessage2(err2)}`);
95135
95528
  }
95136
- } catch {}
95529
+ }
95530
+ for (const file3 of sessionFiles) {
95531
+ if (file3 === "state.json")
95532
+ continue;
95533
+ const filePath = path98.join(sessionDir, file3);
95534
+ try {
95535
+ if (!fs54.existsSync(filePath))
95536
+ continue;
95537
+ if (!fs54.lstatSync(filePath).isFile())
95538
+ continue;
95539
+ fs54.unlinkSync(filePath);
95540
+ results.push(`✓ Deleted ${file3}`);
95541
+ } catch (err2) {
95542
+ results.push(`❌ Failed to delete ${file3}: ${errorMessage2(err2)}`);
95543
+ }
95544
+ }
95137
95545
  const sessionCount = swarmState.agentSessions.size;
95138
95546
  for (const [sessionId, session] of swarmState.agentSessions) {
95139
95547
  resetPrmSessionState(session, sessionId);
@@ -95163,7 +95571,7 @@ var init_reset_session = __esm(() => {
95163
95571
  });
95164
95572
 
95165
95573
  // src/summaries/manager.ts
95166
- import { mkdirSync as mkdirSync29, readdirSync as readdirSync17, renameSync as renameSync17, rmSync as rmSync5, statSync as statSync20 } from "node:fs";
95574
+ import { mkdirSync as mkdirSync29, readdirSync as readdirSync17, renameSync as renameSync19, rmSync as rmSync5, statSync as statSync20 } from "node:fs";
95167
95575
  import * as path99 from "node:path";
95168
95576
  function sanitizeSummaryId(id) {
95169
95577
  if (!id || id.length === 0) {
@@ -95213,7 +95621,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
95213
95621
  const tempPath = path99.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
95214
95622
  try {
95215
95623
  await bunWrite(tempPath, entryJson);
95216
- renameSync17(tempPath, summaryPath);
95624
+ renameSync19(tempPath, summaryPath);
95217
95625
  } catch (error93) {
95218
95626
  try {
95219
95627
  rmSync5(tempPath, { force: true });
@@ -95347,6 +95755,7 @@ async function handleRollbackCommand(directory, args2) {
95347
95755
  ]);
95348
95756
  const successes = [];
95349
95757
  const failures = [];
95758
+ const warnings = [];
95350
95759
  for (const file3 of checkpointFiles) {
95351
95760
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
95352
95761
  continue;
@@ -95372,30 +95781,39 @@ async function handleRollbackCommand(directory, args2) {
95372
95781
  `);
95373
95782
  }
95374
95783
  const existingLedgerPath = path100.join(swarmDir, "plan-ledger.jsonl");
95784
+ let ledgerDeletionFailed = false;
95375
95785
  if (fs55.existsSync(existingLedgerPath)) {
95376
- fs55.unlinkSync(existingLedgerPath);
95377
- }
95378
- try {
95379
- const planJsonPath = path100.join(swarmDir, "plan.json");
95380
- if (fs55.existsSync(planJsonPath)) {
95381
- const planRaw = fs55.readFileSync(planJsonPath, "utf-8");
95382
- const plan = PlanSchema.parse(JSON.parse(planRaw));
95383
- const planId = derivePlanId(plan);
95384
- const planHash = computePlanHash(plan);
95385
- await initLedger(directory, planId, planHash, plan);
95386
- await appendLedgerEvent(directory, {
95387
- event_type: "plan_rebuilt",
95388
- source: "rollback",
95389
- plan_id: planId
95390
- });
95786
+ try {
95787
+ fs55.unlinkSync(existingLedgerPath);
95788
+ } catch (err2) {
95789
+ ledgerDeletionFailed = true;
95790
+ const errMsg = err2 instanceof Error ? err2.message : String(err2);
95791
+ warnings.push(`⚠️ Warning: Could not delete stale ledger (${errMsg}). The ledger may be inconsistent with the restored plan. Run /swarm reset-session to clean up session state.`);
95391
95792
  }
95392
- } catch (initError) {
95393
- return [
95394
- `Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
95395
- "The .swarm/plan.json has been restored but the ledger may be out of sync.",
95396
- "Run /swarm reset-session to reinitialize the ledger."
95397
- ].join(`
95793
+ }
95794
+ if (!ledgerDeletionFailed) {
95795
+ try {
95796
+ const planJsonPath = path100.join(swarmDir, "plan.json");
95797
+ if (fs55.existsSync(planJsonPath)) {
95798
+ const planRaw = fs55.readFileSync(planJsonPath, "utf-8");
95799
+ const plan = PlanSchema.parse(JSON.parse(planRaw));
95800
+ const planId = derivePlanId(plan);
95801
+ const planHash = computePlanHash(plan);
95802
+ await initLedger(directory, planId, planHash, plan);
95803
+ await appendLedgerEvent(directory, {
95804
+ event_type: "plan_rebuilt",
95805
+ source: "rollback",
95806
+ plan_id: planId
95807
+ });
95808
+ }
95809
+ } catch (initError) {
95810
+ return [
95811
+ `Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
95812
+ "The .swarm/plan.json has been restored but the ledger may be out of sync.",
95813
+ "Run /swarm reset-session to reinitialize the ledger."
95814
+ ].join(`
95398
95815
  `);
95816
+ }
95399
95817
  }
95400
95818
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
95401
95819
  const rollbackEvent = {
@@ -95410,6 +95828,14 @@ async function handleRollbackCommand(directory, args2) {
95410
95828
  } catch (error93) {
95411
95829
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
95412
95830
  }
95831
+ if (warnings.length > 0) {
95832
+ return [
95833
+ ...warnings,
95834
+ "",
95835
+ `Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`
95836
+ ].join(`
95837
+ `);
95838
+ }
95413
95839
  return `Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`;
95414
95840
  }
95415
95841
  var init_rollback = __esm(() => {
@@ -95587,6 +96013,7 @@ var init_sdd = __esm(() => {
95587
96013
  });
95588
96014
 
95589
96015
  // src/commands/simulate.ts
96016
+ import { renameSync as renameSync20, unlinkSync as unlinkSync18 } from "node:fs";
95590
96017
  async function handleSimulateCommand(directory, args2) {
95591
96018
  const thresholdIndex = args2.indexOf("--threshold");
95592
96019
  const minCommitsIndex = args2.indexOf("--min-commits");
@@ -95638,7 +96065,16 @@ Ensure this is a git repository with commit history.`;
95638
96065
  const path101 = await import("node:path");
95639
96066
  const reportPath = path101.join(directory, ".swarm", "simulate-report.md");
95640
96067
  await fs56.mkdir(path101.dirname(reportPath), { recursive: true });
95641
- await fs56.writeFile(reportPath, report, "utf-8");
96068
+ const reportTempPath = path101.join(path101.dirname(reportPath), `${path101.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
96069
+ try {
96070
+ await fs56.writeFile(reportTempPath, report, "utf-8");
96071
+ renameSync20(reportTempPath, reportPath);
96072
+ } catch (err2) {
96073
+ try {
96074
+ unlinkSync18(reportTempPath);
96075
+ } catch {}
96076
+ throw err2;
96077
+ }
95642
96078
  } catch (err2) {
95643
96079
  const writeErr = err2 instanceof Error ? err2.message : String(err2);
95644
96080
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -103359,11 +103795,11 @@ __export(exports_evidence_summary_integration, {
103359
103795
  createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
103360
103796
  EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
103361
103797
  });
103362
- import { existsSync as existsSync57, mkdirSync as mkdirSync31, writeFileSync as writeFileSync18 } from "node:fs";
103798
+ import { existsSync as existsSync58, mkdirSync as mkdirSync31, writeFileSync as writeFileSync18 } from "node:fs";
103363
103799
  import * as path107 from "node:path";
103364
103800
  function persistSummary(projectDir, artifact, filename) {
103365
103801
  const swarmPath = path107.join(projectDir, ".swarm");
103366
- if (!existsSync57(swarmPath)) {
103802
+ if (!existsSync58(swarmPath)) {
103367
103803
  mkdirSync31(swarmPath, { recursive: true });
103368
103804
  }
103369
103805
  const artifactPath = path107.join(swarmPath, filename);
@@ -103626,9 +104062,9 @@ function validateFilename(filename) {
103626
104062
  throw new Error("Invalid filename: contains null byte");
103627
104063
  }
103628
104064
  const pathSeparators = ["/", "\\", ".."];
103629
- for (const sep13 of pathSeparators) {
103630
- if (filename.includes(sep13)) {
103631
- throw new Error(`Invalid filename: contains path separator '${sep13}'`);
104065
+ for (const sep14 of pathSeparators) {
104066
+ if (filename.includes(sep14)) {
104067
+ throw new Error(`Invalid filename: contains path separator '${sep14}'`);
103632
104068
  }
103633
104069
  }
103634
104070
  if (filename.startsWith("/") || filename.startsWith("\\") || /^[a-zA-Z]:/.test(filename)) {
@@ -104375,11 +104811,11 @@ var init_schema3 = __esm(() => {
104375
104811
 
104376
104812
  // src/summaries/store.ts
104377
104813
  import {
104378
- existsSync as existsSync69,
104814
+ existsSync as existsSync70,
104379
104815
  mkdirSync as mkdirSync38,
104380
104816
  readFileSync as readFileSync48,
104381
- renameSync as renameSync23,
104382
- unlinkSync as unlinkSync19,
104817
+ renameSync as renameSync26,
104818
+ unlinkSync as unlinkSync22,
104383
104819
  writeFileSync as writeFileSync25
104384
104820
  } from "node:fs";
104385
104821
  import * as path120 from "node:path";
@@ -104388,11 +104824,11 @@ function writeRawSidecar(absPath, bundle) {
104388
104824
  const tempFile = `${absPath}.tmp-${Date.now()}-${process.pid}`;
104389
104825
  try {
104390
104826
  writeFileSync25(tempFile, JSON.stringify(bundle, null, 2), "utf-8");
104391
- renameSync23(tempFile, absPath);
104827
+ renameSync26(tempFile, absPath);
104392
104828
  } finally {
104393
- if (existsSync69(tempFile)) {
104829
+ if (existsSync70(tempFile)) {
104394
104830
  try {
104395
- unlinkSync19(tempFile);
104831
+ unlinkSync22(tempFile);
104396
104832
  } catch {}
104397
104833
  }
104398
104834
  }
@@ -104477,7 +104913,7 @@ function readSupervisorReportRaw(directory, phase) {
104477
104913
  } catch {
104478
104914
  return null;
104479
104915
  }
104480
- if (!existsSync69(abs))
104916
+ if (!existsSync70(abs))
104481
104917
  return null;
104482
104918
  try {
104483
104919
  const parsed = JSON.parse(readFileSync48(abs, "utf-8"));
@@ -107849,7 +108285,7 @@ __export(exports_runtime, {
107849
108285
  clearParserCache: () => clearParserCache,
107850
108286
  _internals: () => _internals80
107851
108287
  });
107852
- import { existsSync as existsSync74, statSync as statSync28 } from "node:fs";
108288
+ import { existsSync as existsSync75, statSync as statSync28 } from "node:fs";
107853
108289
  import * as path133 from "node:path";
107854
108290
  import { fileURLToPath as fileURLToPath4 } from "node:url";
107855
108291
  async function initTreeSitter() {
@@ -107917,7 +108353,7 @@ async function loadGrammar(languageId) {
107917
108353
  const parser = new Parser;
107918
108354
  const wasmFileName = getWasmFileName(normalizedId);
107919
108355
  const wasmPath = path133.join(getGrammarsDirAbsolute(), wasmFileName);
107920
- if (!existsSync74(wasmPath)) {
108356
+ if (!existsSync75(wasmPath)) {
107921
108357
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
107922
108358
  ` + `Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
107923
108359
  }
@@ -108033,17 +108469,17 @@ function normalizeSeparators(filePath) {
108033
108469
  }
108034
108470
  function matchesDocPattern(filePath, patterns) {
108035
108471
  const normalizedPath = normalizeSeparators(filePath);
108036
- const basename15 = path135.basename(filePath);
108472
+ const basename16 = path135.basename(filePath);
108037
108473
  for (const pattern of patterns) {
108038
108474
  if (!pattern.includes("/") && !pattern.includes("\\")) {
108039
- if (basename15 === pattern) {
108475
+ if (basename16 === pattern) {
108040
108476
  return true;
108041
108477
  }
108042
108478
  continue;
108043
108479
  }
108044
108480
  if (pattern.startsWith("**/")) {
108045
108481
  const filenamePattern = pattern.slice(3);
108046
- if (basename15 === filenamePattern) {
108482
+ if (basename16 === filenamePattern) {
108047
108483
  return true;
108048
108484
  }
108049
108485
  continue;
@@ -108436,7 +108872,7 @@ var init_doc_scan = __esm(() => {
108436
108872
  });
108437
108873
 
108438
108874
  // src/hooks/knowledge-reader.ts
108439
- import { existsSync as existsSync75 } from "node:fs";
108875
+ import { existsSync as existsSync76 } from "node:fs";
108440
108876
  import { readFile as readFile28 } from "node:fs/promises";
108441
108877
  import * as path136 from "node:path";
108442
108878
  function inferCategoriesFromPhase(phaseDescription) {
@@ -108484,7 +108920,7 @@ function inferCategoriesFromPhase(phaseDescription) {
108484
108920
  }
108485
108921
  async function transactShownFile(shownFile, mutate) {
108486
108922
  return transactFile(shownFile, async (filePath) => {
108487
- if (!existsSync75(filePath))
108923
+ if (!existsSync76(filePath))
108488
108924
  return {};
108489
108925
  try {
108490
108926
  const content = await readFile28(filePath, "utf-8");
@@ -108614,7 +109050,7 @@ async function readMergedKnowledge(directory, config3, context, opts) {
108614
109050
  async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
108615
109051
  const shownFile = path136.join(directory, ".swarm", ".knowledge-shown.json");
108616
109052
  try {
108617
- if (!existsSync75(shownFile)) {
109053
+ if (!existsSync76(shownFile)) {
108618
109054
  return;
108619
109055
  }
108620
109056
  let shownIds;
@@ -109969,18 +110405,51 @@ var EvidencePlanSchema = exports_external.object({
109969
110405
  }).passthrough()).optional()
109970
110406
  }).passthrough();
109971
110407
  function ghExec(args2, cwd) {
109972
- const result = child_process7.spawnSync("gh", args2, {
109973
- cwd,
109974
- encoding: "utf-8",
109975
- timeout: GIT_TIMEOUT_MS3,
109976
- stdio: ["ignore", "pipe", "pipe"]
109977
- });
109978
- if (result.status !== 0) {
109979
- throw new Error(result.stderr || `gh exited with ${result.status}`);
110408
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
110409
+ const result = child_process7.spawnSync("gh", args2, {
110410
+ cwd,
110411
+ encoding: "utf-8",
110412
+ timeout: GIT_TIMEOUT_MS3,
110413
+ windowsHide: true,
110414
+ maxBuffer: MAX_OUTPUT_BYTES4,
110415
+ stdio: ["ignore", "pipe", "pipe"]
110416
+ });
110417
+ if (result.error) {
110418
+ if (isTransientSpawnError(result.error) && attempt < MAX_TRANSIENT_RETRIES - 1) {
110419
+ transientBackoff(attempt);
110420
+ continue;
110421
+ }
110422
+ if (result.error.code === "ENOENT") {
110423
+ throw new Error(`gh failed to start: ENOENT — gh not installed or not on PATH`);
110424
+ }
110425
+ throw new Error(`gh failed to start: ${result.error.code} — ${result.error.message}`);
110426
+ }
110427
+ if (result.status !== 0) {
110428
+ throw new Error(result.stderr || result.stdout || `gh exited with ${result.status}`);
110429
+ }
110430
+ return result.stdout;
109980
110431
  }
109981
- return result.stdout;
110432
+ throw new Error("gh exited with null");
109982
110433
  }
109983
110434
  var MAX_OUTPUT_BYTES4 = 5 * 1024 * 1024;
110435
+ function spawnSyncWithTransientRetry(command, args2, options) {
110436
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
110437
+ const result = child_process7.spawnSync(command, args2, options);
110438
+ if (result.error) {
110439
+ if (isTransientSpawnError(result.error) && attempt < MAX_TRANSIENT_RETRIES - 1) {
110440
+ transientBackoff(attempt);
110441
+ continue;
110442
+ }
110443
+ throw new Error(`${command} failed: ${result.error.code} — ${result.error.message}`);
110444
+ }
110445
+ if (result.status !== 0) {
110446
+ const reason = result.stderr || result.stdout || `${command} exited with ${result.status}`;
110447
+ throw new Error(`${command} failed: ${reason}`);
110448
+ }
110449
+ return result;
110450
+ }
110451
+ throw new Error(`${command} exited with null`);
110452
+ }
109984
110453
  async function ghExecAsync(args2, cwd) {
109985
110454
  return new Promise((resolve42, reject) => {
109986
110455
  const proc = child_process7.spawn("gh", args2, {
@@ -110042,7 +110511,7 @@ async function ghExecAsync(args2, cwd) {
110042
110511
  });
110043
110512
  });
110044
110513
  }
110045
- var _internals70 = { ghExec, ghExecAsync };
110514
+ var _internals70 = { ghExec, ghExecAsync, spawnSyncWithTransientRetry };
110046
110515
  async function getPRStatus(prNumber, repoFullName, cwd) {
110047
110516
  let stdout;
110048
110517
  try {
@@ -112074,7 +112543,7 @@ init_state2();
112074
112543
  init_utils();
112075
112544
  init_bun_compat();
112076
112545
  init_utils2();
112077
- import { renameSync as renameSync21, unlinkSync as unlinkSync17 } from "node:fs";
112546
+ import { renameSync as renameSync24, unlinkSync as unlinkSync20 } from "node:fs";
112078
112547
  import * as nodePath2 from "node:path";
112079
112548
  function createAgentActivityHooks(config3, directory) {
112080
112549
  if (config3.hooks?.agent_activity === false) {
@@ -112149,10 +112618,10 @@ async function doFlush(directory) {
112149
112618
  const tempPath = `${path116}.tmp`;
112150
112619
  try {
112151
112620
  await bunWrite(tempPath, updated);
112152
- renameSync21(tempPath, path116);
112621
+ renameSync24(tempPath, path116);
112153
112622
  } catch (writeError) {
112154
112623
  try {
112155
- unlinkSync17(tempPath);
112624
+ unlinkSync20(tempPath);
112156
112625
  } catch {}
112157
112626
  throw writeError;
112158
112627
  }
@@ -114331,7 +114800,7 @@ import * as path130 from "node:path";
114331
114800
  init_logger();
114332
114801
  init_path_security();
114333
114802
  import * as fsSync8 from "node:fs";
114334
- import { existsSync as existsSync70, realpathSync as realpathSync13 } from "node:fs";
114803
+ import { existsSync as existsSync71, realpathSync as realpathSync13 } from "node:fs";
114335
114804
  import * as fsPromises5 from "node:fs/promises";
114336
114805
  import * as os16 from "node:os";
114337
114806
  import * as path125 from "node:path";
@@ -115634,7 +116103,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
115634
116103
  if (realRoot === null) {
115635
116104
  return null;
115636
116105
  }
115637
- if (!existsSync70(resolved)) {
116106
+ if (!existsSync71(resolved)) {
115638
116107
  const EXTENSIONS = [
115639
116108
  ".ts",
115640
116109
  ".tsx",
@@ -115648,7 +116117,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
115648
116117
  let found = null;
115649
116118
  for (const ext of EXTENSIONS) {
115650
116119
  const candidate = resolved + ext;
115651
- if (existsSync70(candidate)) {
116120
+ if (existsSync71(candidate)) {
115652
116121
  found = candidate;
115653
116122
  break;
115654
116123
  }
@@ -116115,7 +116584,7 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
116115
116584
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
116116
116585
  const followSymlinks = options?.followSymlinks ?? false;
116117
116586
  const absoluteRoot = path125.resolve(workspaceRoot);
116118
- if (!existsSync70(absoluteRoot)) {
116587
+ if (!existsSync71(absoluteRoot)) {
116119
116588
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
116120
116589
  }
116121
116590
  if (isRefusedWorkspaceRoot(absoluteRoot)) {
@@ -116211,7 +116680,7 @@ function getCachedMtime(workspace) {
116211
116680
  }
116212
116681
  // src/tools/repo-graph/incremental.ts
116213
116682
  init_logger();
116214
- import { existsSync as existsSync72 } from "node:fs";
116683
+ import { existsSync as existsSync73 } from "node:fs";
116215
116684
  import * as fsPromises7 from "node:fs/promises";
116216
116685
  import * as path129 from "node:path";
116217
116686
 
@@ -116777,7 +117246,7 @@ function buildOntologyPreflightPacket(graph, filePaths = [], options = {}) {
116777
117246
  init_utils2();
116778
117247
  init_logger();
116779
117248
  init_path_security();
116780
- import { constants as constants5, existsSync as existsSync71, readFileSync as readFileSync51, statSync as statSync26 } from "node:fs";
117249
+ import { constants as constants5, existsSync as existsSync72, readFileSync as readFileSync51, statSync as statSync26 } from "node:fs";
116781
117250
  import * as fsPromises6 from "node:fs/promises";
116782
117251
  import * as path128 from "node:path";
116783
117252
  var WINDOWS_RENAME_MAX_RETRIES2 = 5;
@@ -116839,7 +117308,7 @@ async function loadGraph(workspace) {
116839
117308
  if (cached3 && !isDirty(normalized)) {
116840
117309
  try {
116841
117310
  const graphPath = getGraphPath(workspace);
116842
- if (existsSync71(graphPath)) {
117311
+ if (existsSync72(graphPath)) {
116843
117312
  const stats2 = await fsPromises6.stat(graphPath);
116844
117313
  const cachedMtime = getCachedMtime(normalized);
116845
117314
  if (cachedMtime !== undefined && stats2.mtimeMs !== cachedMtime) {
@@ -116856,7 +117325,7 @@ async function loadGraph(workspace) {
116856
117325
  }
116857
117326
  try {
116858
117327
  const graphPath = getGraphPath(workspace);
116859
- if (!existsSync71(graphPath)) {
117328
+ if (!existsSync72(graphPath)) {
116860
117329
  return null;
116861
117330
  }
116862
117331
  const stats2 = await fsPromises6.stat(graphPath);
@@ -116890,7 +117359,7 @@ function loadGraphSync(workspace) {
116890
117359
  const normalized = path128.normalize(workspace);
116891
117360
  try {
116892
117361
  const graphPath = getGraphPath(workspace);
116893
- if (!existsSync71(graphPath))
117362
+ if (!existsSync72(graphPath))
116894
117363
  return null;
116895
117364
  const stats2 = statSync26(graphPath);
116896
117365
  const content = readFileSync51(graphPath, "utf-8");
@@ -117020,7 +117489,7 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
117020
117489
  const updatedPaths = new Set;
117021
117490
  for (const rawFilePath of filePaths) {
117022
117491
  const normalizedPath = normalizeGraphPath(rawFilePath);
117023
- const fileExists = existsSync72(rawFilePath);
117492
+ const fileExists = existsSync73(rawFilePath);
117024
117493
  if (fileExists) {
117025
117494
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
117026
117495
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -117060,7 +117529,7 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
117060
117529
  if (loadedMtime !== undefined) {
117061
117530
  try {
117062
117531
  const graphPath = getGraphPath(workspaceRoot);
117063
- if (existsSync72(graphPath)) {
117532
+ if (existsSync73(graphPath)) {
117064
117533
  const currentStats = await fsPromises7.stat(graphPath);
117065
117534
  if (currentStats.mtimeMs !== loadedMtime) {
117066
117535
  warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
@@ -121221,7 +121690,7 @@ init_task_file();
121221
121690
  init_logger();
121222
121691
  init_knowledge_store();
121223
121692
  var import_proper_lockfile9 = __toESM(require_proper_lockfile(), 1);
121224
- import { existsSync as existsSync77 } from "node:fs";
121693
+ import { existsSync as existsSync78 } from "node:fs";
121225
121694
  import { appendFile as appendFile13, mkdir as mkdir28, readFile as readFile30 } from "node:fs/promises";
121226
121695
  import * as path140 from "node:path";
121227
121696
  function resolveApplicationLogPath(directory) {
@@ -121310,7 +121779,7 @@ async function bumpCountersBatch(directory, bumps) {
121310
121779
  const swarmPath = resolveSwarmKnowledgePath(directory);
121311
121780
  await transactKnowledge(swarmPath, applyOne);
121312
121781
  const hivePath = resolveHiveKnowledgePath();
121313
- if (existsSync77(hivePath)) {
121782
+ if (existsSync78(hivePath)) {
121314
121783
  await transactKnowledge(hivePath, applyOne);
121315
121784
  }
121316
121785
  }
@@ -122284,7 +122753,7 @@ init_extractors();
122284
122753
  // src/hooks/phase-directives.ts
122285
122754
  init_knowledge_events();
122286
122755
  init_knowledge_store();
122287
- import { existsSync as existsSync78 } from "node:fs";
122756
+ import { existsSync as existsSync79 } from "node:fs";
122288
122757
  async function collectPhaseDirectiveIds(directory, phaseLabel) {
122289
122758
  const events = await readKnowledgeEvents(directory);
122290
122759
  const ids = new Set;
@@ -122304,7 +122773,7 @@ async function readEntriesById(directory) {
122304
122773
  for (const e of swarm)
122305
122774
  map3.set(e.id, e);
122306
122775
  const hivePath = resolveHiveKnowledgePath();
122307
- if (existsSync78(hivePath)) {
122776
+ if (existsSync79(hivePath)) {
122308
122777
  const hive = await readKnowledge(hivePath);
122309
122778
  for (const e of hive)
122310
122779
  if (!map3.has(e.id))
@@ -124196,7 +124665,7 @@ init_schema();
124196
124665
  // src/services/directive-predicate-runner.ts
124197
124666
  init_bun_compat();
124198
124667
  init_logger();
124199
- import { existsSync as existsSync81 } from "node:fs";
124668
+ import { existsSync as existsSync82 } from "node:fs";
124200
124669
  import * as path146 from "node:path";
124201
124670
  var PREDICATE_TIMEOUT_MS = 15000;
124202
124671
  var TOOL_BINARY_ALLOWLIST = new Set([
@@ -124238,7 +124707,7 @@ function findBinaryInPath(binary2) {
124238
124707
  if (!dir)
124239
124708
  continue;
124240
124709
  const candidate = path146.join(dir, exeName);
124241
- if (existsSync81(candidate))
124710
+ if (existsSync82(candidate))
124242
124711
  return candidate;
124243
124712
  }
124244
124713
  return null;
@@ -125070,7 +125539,7 @@ init_state3();
125070
125539
  init_utils2();
125071
125540
  init_state2();
125072
125541
  init_bun_compat();
125073
- import { renameSync as renameSync25 } from "node:fs";
125542
+ import { renameSync as renameSync28 } from "node:fs";
125074
125543
  var TRANSIENT_SESSION_FIELDS = [
125075
125544
  { name: "revisionLimitHit", resetValue: false },
125076
125545
  { name: "coderRevisions", resetValue: 0 },
@@ -125213,7 +125682,7 @@ async function readSnapshot(directory) {
125213
125682
  if (parsed.version !== 1 && parsed.version !== 2) {
125214
125683
  try {
125215
125684
  const quarantinePath = validateSwarmPath(directory, "session/state.json.quarantine");
125216
- renameSync25(resolvedPath, quarantinePath);
125685
+ renameSync28(resolvedPath, quarantinePath);
125217
125686
  } catch {}
125218
125687
  return null;
125219
125688
  }
@@ -125312,14 +125781,14 @@ init_zod();
125312
125781
  init_path_security();
125313
125782
  init_create_tool();
125314
125783
  import {
125315
- existsSync as existsSync83,
125784
+ existsSync as existsSync84,
125316
125785
  mkdirSync as mkdirSync39,
125317
125786
  mkdtempSync as mkdtempSync2,
125318
125787
  readFileSync as readFileSync56,
125319
125788
  realpathSync as realpathSync16,
125320
- renameSync as renameSync26,
125789
+ renameSync as renameSync29,
125321
125790
  rmdirSync,
125322
- unlinkSync as unlinkSync22,
125791
+ unlinkSync as unlinkSync25,
125323
125792
  writeFileSync as writeFileSync26
125324
125793
  } from "node:fs";
125325
125794
  import * as path149 from "node:path";
@@ -125673,15 +126142,15 @@ function atomicWriteFileSync2(targetPath, content) {
125673
126142
  }
125674
126143
  try {
125675
126144
  writeFileSync26(tempPath, content, "utf-8");
125676
- renameSync26(tempPath, targetPath);
126145
+ renameSync29(tempPath, targetPath);
125677
126146
  } finally {
125678
- if (existsSync83(tempPath)) {
126147
+ if (existsSync84(tempPath)) {
125679
126148
  try {
125680
- unlinkSync22(tempPath);
126149
+ unlinkSync25(tempPath);
125681
126150
  } catch {}
125682
126151
  }
125683
126152
  const tempDir = path149.dirname(tempPath);
125684
- if (tempDir !== dir && existsSync83(tempDir)) {
126153
+ if (tempDir !== dir && existsSync84(tempDir)) {
125685
126154
  try {
125686
126155
  rmdirSync(tempDir);
125687
126156
  } catch {}
@@ -125758,7 +126227,7 @@ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allo
125758
126227
  };
125759
126228
  }
125760
126229
  const parentDir = path149.dirname(fullPath);
125761
- if (!existsSync83(parentDir)) {
126230
+ if (!existsSync84(parentDir)) {
125762
126231
  return {
125763
126232
  file: targetPath,
125764
126233
  status: "error",
@@ -125774,7 +126243,7 @@ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allo
125774
126243
  ]
125775
126244
  };
125776
126245
  }
125777
- if (existsSync83(fullPath)) {
126246
+ if (existsSync84(fullPath)) {
125778
126247
  return {
125779
126248
  file: targetPath,
125780
126249
  status: "error",
@@ -125849,7 +126318,7 @@ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allo
125849
126318
  ]
125850
126319
  };
125851
126320
  }
125852
- if (!existsSync83(fullPath)) {
126321
+ if (!existsSync84(fullPath)) {
125853
126322
  return {
125854
126323
  file: targetPath,
125855
126324
  status: "error",
@@ -125867,7 +126336,7 @@ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allo
125867
126336
  }
125868
126337
  if (!dryRun) {
125869
126338
  try {
125870
- unlinkSync22(fullPath);
126339
+ unlinkSync25(fullPath);
125871
126340
  } catch (err2) {
125872
126341
  return {
125873
126342
  file: targetPath,
@@ -125893,7 +126362,7 @@ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allo
125893
126362
  hunksFailed: 0
125894
126363
  };
125895
126364
  }
125896
- if (!existsSync83(fullPath)) {
126365
+ if (!existsSync84(fullPath)) {
125897
126366
  return {
125898
126367
  file: targetPath,
125899
126368
  status: "error",
@@ -126044,7 +126513,7 @@ var applyPatch = createSwarmTool({
126044
126513
  const dryRun = obj.dryRun ?? false;
126045
126514
  const allowCreates = obj.allowCreates ?? false;
126046
126515
  const allowDeletes = obj.allowDeletes ?? false;
126047
- if (!existsSync83(directory)) {
126516
+ if (!existsSync84(directory)) {
126048
126517
  return JSON.stringify(buildErrorResult("Workspace directory does not exist"), null, 2);
126049
126518
  }
126050
126519
  if (files.length === 0) {
@@ -127234,7 +127703,7 @@ function countCodeLines(content) {
127234
127703
  return lines.length;
127235
127704
  }
127236
127705
  function isTestFile(filePath) {
127237
- const basename17 = path153.basename(filePath);
127706
+ const basename18 = path153.basename(filePath);
127238
127707
  const _ext = path153.extname(filePath).toLowerCase();
127239
127708
  const testPatterns = [
127240
127709
  ".test.",
@@ -127250,7 +127719,7 @@ function isTestFile(filePath) {
127250
127719
  ".spec.jsx"
127251
127720
  ];
127252
127721
  for (const pattern of testPatterns) {
127253
- if (basename17.includes(pattern)) {
127722
+ if (basename18.includes(pattern)) {
127254
127723
  return true;
127255
127724
  }
127256
127725
  }
@@ -127863,7 +128332,7 @@ ${body2}`);
127863
128332
  // src/council/council-evidence-writer.ts
127864
128333
  init_zod();
127865
128334
  init_task_file();
127866
- import { appendFileSync as appendFileSync18, existsSync as existsSync88, mkdirSync as mkdirSync41, readFileSync as readFileSync62 } from "node:fs";
128335
+ import { appendFileSync as appendFileSync18, existsSync as existsSync89, mkdirSync as mkdirSync41, readFileSync as readFileSync62 } from "node:fs";
127867
128336
  import { join as join122 } from "node:path";
127868
128337
  var EVIDENCE_DIR2 = ".swarm/evidence";
127869
128338
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
@@ -127907,7 +128376,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
127907
128376
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
127908
128377
  await _internals88.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
127909
128378
  const existingRoot = Object.create(null);
127910
- if (existsSync88(filePath)) {
128379
+ if (existsSync89(filePath)) {
127911
128380
  try {
127912
128381
  const parsed = EvidenceFileSchema.parse(JSON.parse(readFileSync62(filePath, "utf-8")));
127913
128382
  safeAssignOwnProps(existingRoot, parsed);
@@ -128302,7 +128771,7 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
128302
128771
  // src/council/criteria-store.ts
128303
128772
  init_zod();
128304
128773
  init_task_file();
128305
- import { existsSync as existsSync89, mkdirSync as mkdirSync42, readFileSync as readFileSync63 } from "node:fs";
128774
+ import { existsSync as existsSync90, mkdirSync as mkdirSync42, readFileSync as readFileSync63 } from "node:fs";
128306
128775
  import { join as join123 } from "node:path";
128307
128776
  var COUNCIL_DIR = ".swarm/council";
128308
128777
  var CouncilCriteriaSchema = exports_external.object({
@@ -128326,7 +128795,7 @@ async function writeCriteria(workingDir, taskId, criteria) {
128326
128795
  }
128327
128796
  function readCriteria(workingDir, taskId) {
128328
128797
  const filePath = join123(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
128329
- if (!existsSync89(filePath))
128798
+ if (!existsSync90(filePath))
128330
128799
  return null;
128331
128800
  try {
128332
128801
  return CouncilCriteriaSchema.parse(JSON.parse(readFileSync63(filePath, "utf-8")));
@@ -130050,11 +130519,11 @@ init_zod();
130050
130519
  init_utils2();
130051
130520
  import { createHash as createHash18 } from "node:crypto";
130052
130521
  import {
130053
- existsSync as existsSync91,
130522
+ existsSync as existsSync92,
130054
130523
  mkdirSync as mkdirSync43,
130055
130524
  readFileSync as readFileSync66,
130056
- renameSync as renameSync27,
130057
- unlinkSync as unlinkSync23,
130525
+ renameSync as renameSync30,
130526
+ unlinkSync as unlinkSync26,
130058
130527
  writeFileSync as writeFileSync28
130059
130528
  } from "node:fs";
130060
130529
  import * as path159 from "node:path";
@@ -130101,7 +130570,7 @@ function storeLaneOutput(directory, input, now = Date.now) {
130101
130570
  const absPath = validateSwarmPath(directory, relPath);
130102
130571
  const timestamp = new Date(now()).toISOString();
130103
130572
  try {
130104
- if (existsSync91(absPath)) {
130573
+ if (existsSync92(absPath)) {
130105
130574
  const existing = LaneOutputArtifactSchema.safeParse(JSON.parse(readFileSync66(absPath, "utf-8")));
130106
130575
  if (existing.success && existing.data.digest === digest3) {
130107
130576
  return {
@@ -130155,7 +130624,7 @@ function readLaneOutput(directory, ref) {
130155
130624
  if (!REF_RE.test(ref))
130156
130625
  return null;
130157
130626
  const absPath = validateSwarmPath(directory, laneOutputRelativePath(ref));
130158
- if (!existsSync91(absPath))
130627
+ if (!existsSync92(absPath))
130159
130628
  return null;
130160
130629
  let parsed;
130161
130630
  try {
@@ -130244,7 +130713,7 @@ function writeAtomicJson(absPath, value) {
130244
130713
  let lastRenameError;
130245
130714
  for (let attempt = 0;attempt < WINDOWS_RENAME_MAX_RETRIES3; attempt++) {
130246
130715
  try {
130247
- renameSync27(tempFile, absPath);
130716
+ renameSync30(tempFile, absPath);
130248
130717
  lastRenameError = undefined;
130249
130718
  break;
130250
130719
  } catch (err2) {
@@ -130257,9 +130726,9 @@ function writeAtomicJson(absPath, value) {
130257
130726
  if (lastRenameError)
130258
130727
  throw lastRenameError;
130259
130728
  } finally {
130260
- if (existsSync91(tempFile)) {
130729
+ if (existsSync92(tempFile)) {
130261
130730
  try {
130262
- unlinkSync23(tempFile);
130731
+ unlinkSync26(tempFile);
130263
130732
  } catch {}
130264
130733
  }
130265
130734
  }
@@ -137109,7 +137578,7 @@ init_zod();
137109
137578
  init_config();
137110
137579
  init_knowledge_store();
137111
137580
  init_create_tool();
137112
- import { existsSync as existsSync97 } from "node:fs";
137581
+ import { existsSync as existsSync98 } from "node:fs";
137113
137582
  var DEFAULT_LIMIT = 10;
137114
137583
  var MAX_LESSON_LENGTH = 200;
137115
137584
  var VALID_CATEGORIES3 = [
@@ -137185,14 +137654,14 @@ function validateLimit(limit) {
137185
137654
  }
137186
137655
  async function readSwarmKnowledge(directory) {
137187
137656
  const swarmPath = resolveSwarmKnowledgePath(directory);
137188
- if (!existsSync97(swarmPath)) {
137657
+ if (!existsSync98(swarmPath)) {
137189
137658
  return [];
137190
137659
  }
137191
137660
  return readKnowledge(swarmPath);
137192
137661
  }
137193
137662
  async function readHiveKnowledge() {
137194
137663
  const hivePath = resolveHiveKnowledgePath();
137195
- if (!existsSync97(hivePath)) {
137664
+ if (!existsSync98(hivePath)) {
137196
137665
  return [];
137197
137666
  }
137198
137667
  return readKnowledge(hivePath);
@@ -138016,8 +138485,8 @@ import * as fs109 from "node:fs";
138016
138485
  import * as path170 from "node:path";
138017
138486
 
138018
138487
  // src/mutation/engine.ts
138019
- import { spawnSync as spawnSync12 } from "node:child_process";
138020
- import { unlinkSync as unlinkSync24, writeFileSync as writeFileSync30 } from "node:fs";
138488
+ import { spawnSync as spawnSync13 } from "node:child_process";
138489
+ import { unlinkSync as unlinkSync27, writeFileSync as writeFileSync30 } from "node:fs";
138021
138490
  import * as path169 from "node:path";
138022
138491
 
138023
138492
  // src/mutation/equivalence.ts
@@ -138194,7 +138663,7 @@ var _internals106 = {
138194
138663
  executeMutation,
138195
138664
  computeReport,
138196
138665
  executeMutationSuite,
138197
- spawnSync: spawnSync12
138666
+ spawnSync: spawnSync13
138198
138667
  };
138199
138668
  async function executeMutation(patch, testCommand, testFiles, workingDir) {
138200
138669
  const startTime = Date.now();
@@ -138305,7 +138774,7 @@ async function executeMutation(patch, testCommand, testFiles, workingDir) {
138305
138774
  revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
138306
138775
  }
138307
138776
  try {
138308
- unlinkSync24(patchFile);
138777
+ unlinkSync27(patchFile);
138309
138778
  } catch (_unlinkErr) {}
138310
138779
  }
138311
138780
  }
@@ -141202,8 +141671,8 @@ async function runNpmAudit(directory) {
141202
141671
  clean: findings.length === 0
141203
141672
  };
141204
141673
  } catch (error93) {
141205
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
141206
- if (errorMessage2.includes("audit") || errorMessage2.includes("command not found") || errorMessage2.includes("'npm' is not recognized")) {
141674
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141675
+ if (errorMessage3.includes("audit") || errorMessage3.includes("command not found") || errorMessage3.includes("'npm' is not recognized")) {
141207
141676
  return {
141208
141677
  ecosystem: "npm",
141209
141678
  command,
@@ -141223,7 +141692,7 @@ async function runNpmAudit(directory) {
141223
141692
  highCount: 0,
141224
141693
  totalCount: 0,
141225
141694
  clean: true,
141226
- note: `Error running npm audit: ${errorMessage2}`
141695
+ note: `Error running npm audit: ${errorMessage3}`
141227
141696
  };
141228
141697
  }
141229
141698
  }
@@ -141344,8 +141813,8 @@ async function runPipAudit(directory) {
141344
141813
  clean: findings.length === 0
141345
141814
  };
141346
141815
  } catch (error93) {
141347
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
141348
- if (errorMessage2.includes("not found") || errorMessage2.includes("not recognized") || errorMessage2.includes("pip-audit")) {
141816
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141817
+ if (errorMessage3.includes("not found") || errorMessage3.includes("not recognized") || errorMessage3.includes("pip-audit")) {
141349
141818
  return {
141350
141819
  ecosystem: "pip",
141351
141820
  command,
@@ -141365,7 +141834,7 @@ async function runPipAudit(directory) {
141365
141834
  highCount: 0,
141366
141835
  totalCount: 0,
141367
141836
  clean: true,
141368
- note: `Error running pip-audit: ${errorMessage2}`
141837
+ note: `Error running pip-audit: ${errorMessage3}`
141369
141838
  };
141370
141839
  }
141371
141840
  }
@@ -141446,8 +141915,8 @@ async function runCargoAudit(directory) {
141446
141915
  clean: findings.length === 0
141447
141916
  };
141448
141917
  } catch (error93) {
141449
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
141450
- if (errorMessage2.includes("not found") || errorMessage2.includes("not recognized") || errorMessage2.includes("cargo-audit")) {
141918
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141919
+ if (errorMessage3.includes("not found") || errorMessage3.includes("not recognized") || errorMessage3.includes("cargo-audit")) {
141451
141920
  return {
141452
141921
  ecosystem: "cargo",
141453
141922
  command,
@@ -141467,7 +141936,7 @@ async function runCargoAudit(directory) {
141467
141936
  highCount: 0,
141468
141937
  totalCount: 0,
141469
141938
  clean: true,
141470
- note: `Error running cargo audit: ${errorMessage2}`
141939
+ note: `Error running cargo audit: ${errorMessage3}`
141471
141940
  };
141472
141941
  }
141473
141942
  }
@@ -141594,7 +142063,7 @@ async function runGoAudit(directory) {
141594
142063
  clean: findings.length === 0
141595
142064
  };
141596
142065
  } catch (error93) {
141597
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
142066
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141598
142067
  return {
141599
142068
  ecosystem: "go",
141600
142069
  command,
@@ -141603,7 +142072,7 @@ async function runGoAudit(directory) {
141603
142072
  highCount: 0,
141604
142073
  totalCount: 0,
141605
142074
  clean: true,
141606
- note: `Error running govulncheck: ${errorMessage2}`
142075
+ note: `Error running govulncheck: ${errorMessage3}`
141607
142076
  };
141608
142077
  }
141609
142078
  }
@@ -141701,7 +142170,7 @@ async function runDotnetAudit(directory) {
141701
142170
  clean: findings.length === 0
141702
142171
  };
141703
142172
  } catch (error93) {
141704
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
142173
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141705
142174
  return {
141706
142175
  ecosystem: "dotnet",
141707
142176
  command,
@@ -141710,7 +142179,7 @@ async function runDotnetAudit(directory) {
141710
142179
  highCount: 0,
141711
142180
  totalCount: 0,
141712
142181
  clean: true,
141713
- note: `Error running dotnet list package: ${errorMessage2}`
142182
+ note: `Error running dotnet list package: ${errorMessage3}`
141714
142183
  };
141715
142184
  }
141716
142185
  }
@@ -141837,8 +142306,8 @@ async function runBundleAudit(directory) {
141837
142306
  clean: findings.length === 0
141838
142307
  };
141839
142308
  } catch (error93) {
141840
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
141841
- const isNotInstalled = errorMessage2.includes("not recognized") || errorMessage2.includes("not found") || errorMessage2.includes("No such file") || errorMessage2.includes("ENOENT");
142309
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
142310
+ const isNotInstalled = errorMessage3.includes("not recognized") || errorMessage3.includes("not found") || errorMessage3.includes("No such file") || errorMessage3.includes("ENOENT");
141842
142311
  return {
141843
142312
  ecosystem: "ruby",
141844
142313
  command,
@@ -141847,7 +142316,7 @@ async function runBundleAudit(directory) {
141847
142316
  highCount: 0,
141848
142317
  totalCount: 0,
141849
142318
  clean: true,
141850
- note: isNotInstalled ? "bundle-audit not installed. Install with: gem install bundler-audit" : `Error running bundle-audit: ${errorMessage2}`
142319
+ note: isNotInstalled ? "bundle-audit not installed. Install with: gem install bundler-audit" : `Error running bundle-audit: ${errorMessage3}`
141851
142320
  };
141852
142321
  }
141853
142322
  }
@@ -141976,7 +142445,7 @@ async function runDartAudit(directory) {
141976
142445
  note: "dart pub outdated reports outdated packages, not security vulnerabilities"
141977
142446
  };
141978
142447
  } catch (error93) {
141979
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
142448
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
141980
142449
  return {
141981
142450
  ecosystem: "dart",
141982
142451
  command,
@@ -141985,7 +142454,7 @@ async function runDartAudit(directory) {
141985
142454
  highCount: 0,
141986
142455
  totalCount: 0,
141987
142456
  clean: true,
141988
- note: `Error running dart pub outdated: ${errorMessage2}`
142457
+ note: `Error running dart pub outdated: ${errorMessage3}`
141989
142458
  };
141990
142459
  }
141991
142460
  }
@@ -143860,11 +144329,11 @@ async function runSemgrep(options) {
143860
144329
  engine: "tier_a+tier_b"
143861
144330
  };
143862
144331
  } catch (error93) {
143863
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error running Semgrep";
144332
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error running Semgrep";
143864
144333
  return {
143865
144334
  available: true,
143866
144335
  findings: [],
143867
- error: errorMessage2,
144336
+ error: errorMessage3,
143868
144337
  engine: "tier_a"
143869
144338
  };
143870
144339
  }
@@ -145381,13 +145850,13 @@ var pre_check_batch = createSwarmTool({
145381
145850
  }, workspaceAnchor, directory);
145382
145851
  return JSON.stringify(result, null, 2);
145383
145852
  } catch (error93) {
145384
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
145853
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
145385
145854
  const errorResult = {
145386
145855
  gates_passed: false,
145387
- lint: { ran: false, error: errorMessage2, duration_ms: 0 },
145388
- secretscan: { ran: false, error: errorMessage2, duration_ms: 0 },
145389
- sast_scan: { ran: false, error: errorMessage2, duration_ms: 0 },
145390
- quality_budget: { ran: false, error: errorMessage2, duration_ms: 0 },
145856
+ lint: { ran: false, error: errorMessage3, duration_ms: 0 },
145857
+ secretscan: { ran: false, error: errorMessage3, duration_ms: 0 },
145858
+ sast_scan: { ran: false, error: errorMessage3, duration_ms: 0 },
145859
+ quality_budget: { ran: false, error: errorMessage3, duration_ms: 0 },
145391
145860
  total_duration_ms: 0
145392
145861
  };
145393
145862
  return JSON.stringify(errorResult, null, 2);
@@ -148008,7 +148477,7 @@ var schema_drift = createSwarmTool({
148008
148477
  };
148009
148478
  return JSON.stringify(result, null, 2);
148010
148479
  } catch (error93) {
148011
- const errorMessage2 = error93 instanceof Error ? error93.message : "Unknown error";
148480
+ const errorMessage3 = error93 instanceof Error ? error93.message : "Unknown error";
148012
148481
  const errorResult = {
148013
148482
  specFile: "",
148014
148483
  specPathCount: 0,
@@ -148019,7 +148488,7 @@ var schema_drift = createSwarmTool({
148019
148488
  phantomCount: 0,
148020
148489
  consistent: false
148021
148490
  };
148022
- return JSON.stringify({ ...errorResult, error: errorMessage2 }, null, 2);
148491
+ return JSON.stringify({ ...errorResult, error: errorMessage3 }, null, 2);
148023
148492
  }
148024
148493
  }
148025
148494
  });
@@ -148762,11 +149231,11 @@ ${content}
148762
149231
  init_zod();
148763
149232
  init_loader();
148764
149233
  import {
148765
- existsSync as existsSync111,
149234
+ existsSync as existsSync112,
148766
149235
  mkdirSync as mkdirSync49,
148767
149236
  readFileSync as readFileSync89,
148768
- renameSync as renameSync29,
148769
- unlinkSync as unlinkSync26,
149237
+ renameSync as renameSync32,
149238
+ unlinkSync as unlinkSync29,
148770
149239
  writeFileSync as writeFileSync36
148771
149240
  } from "node:fs";
148772
149241
  import path194 from "node:path";
@@ -149035,10 +149504,10 @@ function writePhaseCouncilEvidence(workingDir, synthesis, provenance) {
149035
149504
  const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
149036
149505
  try {
149037
149506
  writeFileSync36(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
149038
- renameSync29(tempFile, evidenceFile);
149507
+ renameSync32(tempFile, evidenceFile);
149039
149508
  } finally {
149040
- if (existsSync111(tempFile)) {
149041
- unlinkSync26(tempFile);
149509
+ if (existsSync112(tempFile)) {
149510
+ unlinkSync29(tempFile);
149042
149511
  }
149043
149512
  }
149044
149513
  }