opencode-swarm 7.87.1 → 7.87.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,14 +11,16 @@ import {
11
11
  quarantineEntry,
12
12
  readKnowledgeCounterRollups,
13
13
  readKnowledgeEvents,
14
+ regenerateSkill,
14
15
  resolveKnowledgeEventsPath,
15
16
  resolveUnactionablePath,
16
17
  restoreEntry,
18
+ retireSkill,
17
19
  selectCandidateEntries,
18
20
  validateActionability,
19
21
  validateActionableFields,
20
22
  validateLesson
21
- } from "./index-s8bj492g.js";
23
+ } from "./index-32axfg6h.js";
22
24
  import {
23
25
  appendKnowledge,
24
26
  appendRejectedLesson,
@@ -60,6 +62,7 @@ import {
60
62
  stripKnownSwarmPrefix
61
63
  } from "./index-q9h0wb04.js";
62
64
  import {
65
+ MAX_TRANSIENT_RETRIES,
63
66
  PlanSchema,
64
67
  RetrospectiveEvidenceSchema,
65
68
  appendLedgerEvent,
@@ -81,6 +84,7 @@ import {
81
84
  isGlobalFile,
82
85
  isProtectedPath,
83
86
  isStateUnreadable,
87
+ isTransientSpawnError,
84
88
  isValidEvidenceType,
85
89
  listEvidenceTaskIds,
86
90
  loadEpicSessionState,
@@ -97,9 +101,10 @@ import {
97
101
  sanitizeTaskId,
98
102
  saveEvidence,
99
103
  savePlan,
104
+ transientBackoff,
100
105
  validateProjectRoot,
101
106
  writeProjectedSpecSync
102
- } from "./index-89xjr3h4.js";
107
+ } from "./index-8y7qetpg.js";
103
108
  import {
104
109
  _internals as _internals2,
105
110
  _internals1 as _internals3,
@@ -894,7 +899,7 @@ var init_executor = __esm(() => {
894
899
  // package.json
895
900
  var package_default = {
896
901
  name: "opencode-swarm",
897
- version: "7.87.1",
902
+ version: "7.87.3",
898
903
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
899
904
  main: "dist/index.js",
900
905
  types: "dist/index.d.ts",
@@ -5231,6 +5236,7 @@ function createSwarmTool(opts) {
5231
5236
  var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
5232
5237
  var MAX_LABEL_LENGTH = 100;
5233
5238
  var GIT_TIMEOUT_MS = 30000;
5239
+ var GIT_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
5234
5240
  var SHELL_METACHARACTERS = /[;|&$`(){}<>!'"]/;
5235
5241
  var SAFE_LABEL_PATTERN = /^[a-zA-Z0-9_ -]+$/;
5236
5242
  var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
@@ -5305,20 +5311,31 @@ function writeCheckpointLog(log2, directory) {
5305
5311
  fs7.renameSync(tempPath, logPath);
5306
5312
  }
5307
5313
  function gitExec(args, cwd) {
5308
- const result = child_process.spawnSync("git", args, {
5309
- cwd,
5310
- encoding: "utf-8",
5311
- timeout: GIT_TIMEOUT_MS,
5312
- stdio: ["ignore", "pipe", "pipe"],
5313
- windowsHide: true
5314
- });
5315
- if (result.error) {
5316
- throw new Error(`git failed to start: ${result.error.code ?? "unknown"} \u2014 ${result.error.message}`);
5317
- }
5318
- if (result.status !== 0) {
5314
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
5315
+ const result = child_process.spawnSync("git", args, {
5316
+ cwd,
5317
+ encoding: "utf-8",
5318
+ timeout: GIT_TIMEOUT_MS,
5319
+ stdio: ["ignore", "pipe", "pipe"],
5320
+ windowsHide: true,
5321
+ maxBuffer: GIT_MAX_BUFFER_BYTES
5322
+ });
5323
+ if (result.error) {
5324
+ const code = result.error.code;
5325
+ const message = result.error.message ?? "";
5326
+ const isTransient = isTransientSpawnError(result.error) || /ETIMEDOUT|timed out/i.test(message);
5327
+ if (!isTransient || attempt >= MAX_TRANSIENT_RETRIES - 1) {
5328
+ throw new Error(`git failed to start: ${code ?? "unknown"} \u2014 ${message}`);
5329
+ }
5330
+ transientBackoff(attempt);
5331
+ continue;
5332
+ }
5333
+ if (result.status === 0) {
5334
+ return result.stdout ?? "";
5335
+ }
5319
5336
  throw new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
5320
5337
  }
5321
- return result.stdout;
5338
+ throw new Error("git command failed after transient retries");
5322
5339
  }
5323
5340
  function appendRetentionEvent(directory, event) {
5324
5341
  try {
@@ -5335,9 +5352,20 @@ function getCurrentSha(directory) {
5335
5352
  function isGitRepo2(directory) {
5336
5353
  try {
5337
5354
  gitExec(["rev-parse", "--git-dir"], directory);
5338
- return true;
5339
- } catch {
5340
- return false;
5355
+ return { isRepo: true };
5356
+ } catch (e) {
5357
+ const message = e instanceof Error ? e.message : String(e);
5358
+ const isTransient = /ETIMEDOUT|timed out/i.test(message) && !/not a git repository/i.test(message);
5359
+ if (isTransient) {
5360
+ return {
5361
+ isRepo: false,
5362
+ warning: "git probe failed after retry exhaustion \u2014 treating as not a git repository"
5363
+ };
5364
+ }
5365
+ return {
5366
+ isRepo: false,
5367
+ warning: "git probe failed \u2014 directory may not be a git repository"
5368
+ };
5341
5369
  }
5342
5370
  }
5343
5371
  function handleSave(label, directory) {
@@ -5480,11 +5508,12 @@ var checkpoint = createSwarmTool({
5480
5508
  label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
5481
5509
  },
5482
5510
  execute: async (args, directory) => {
5483
- if (!isGitRepo2(directory)) {
5511
+ const repoProbe = isGitRepo2(directory);
5512
+ if (!repoProbe.isRepo) {
5484
5513
  return JSON.stringify({
5485
5514
  action: "unknown",
5486
5515
  success: false,
5487
- error: "not a git repository"
5516
+ error: `${repoProbe.warning ?? "not a git repository"} \u2014 checkpoint tools require a git repository`
5488
5517
  }, null, 2);
5489
5518
  }
5490
5519
  let action;
@@ -5673,6 +5702,7 @@ async function handleClarifyCommand(_directory, args) {
5673
5702
  }
5674
5703
 
5675
5704
  // src/commands/close.ts
5705
+ import { spawnSync as spawnSync5 } from "child_process";
5676
5706
  import * as fsSync2 from "fs";
5677
5707
  import { promises as fs11 } from "fs";
5678
5708
  import path24 from "path";
@@ -6079,7 +6109,8 @@ async function runCuratorPostMortem(directory, options = {}) {
6079
6109
  } catch {
6080
6110
  warnings.push("Failed to load plan data.");
6081
6111
  }
6082
- const reportFilename = `post-mortem-${planId}.md`;
6112
+ const effectivePlanId = planId === "unknown" ? `unknown-${Date.now()}` : planId;
6113
+ const reportFilename = `post-mortem-${effectivePlanId}.md`;
6083
6114
  let reportPath;
6084
6115
  try {
6085
6116
  reportPath = validateSwarmPath(directory, reportFilename);
@@ -6095,22 +6126,22 @@ async function runCuratorPostMortem(directory, options = {}) {
6095
6126
  if (!options.force && isReportValid(reportPath)) {
6096
6127
  return {
6097
6128
  success: true,
6098
- planId,
6129
+ planId: effectivePlanId,
6099
6130
  reportPath,
6100
6131
  summary: "Post-mortem report already exists (idempotent skip).",
6101
6132
  warnings
6102
6133
  };
6103
6134
  }
6104
- const lock = await _internals13.acquirePostMortemLock(directory, planId);
6135
+ const lock = await _internals13.acquirePostMortemLock(directory, effectivePlanId);
6105
6136
  if (!lock.acquired) {
6106
6137
  return {
6107
6138
  success: false,
6108
- planId,
6139
+ planId: effectivePlanId,
6109
6140
  reportPath,
6110
6141
  summary: null,
6111
6142
  warnings: [
6112
6143
  ...warnings,
6113
- `Concurrent post-mortem run in progress for plan ${planId}; skipped.`
6144
+ `Concurrent post-mortem run in progress for plan ${effectivePlanId}; skipped.`
6114
6145
  ]
6115
6146
  };
6116
6147
  }
@@ -6160,7 +6191,7 @@ async function runCuratorPostMortem(directory, options = {}) {
6160
6191
  if (options.llmDelegate) {
6161
6192
  try {
6162
6193
  const { CURATOR_POSTMORTEM_PROMPT: CURATOR_POSTMORTEM_PROMPT2 } = await import("./explorer-gz70sm9b.js");
6163
- const userInput = assembleLLMInput(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6194
+ const userInput = assembleLLMInput(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6164
6195
  const ac = new AbortController;
6165
6196
  const timer = setTimeout(() => ac.abort(), 300000);
6166
6197
  let llmOutput;
@@ -6176,17 +6207,17 @@ async function runCuratorPostMortem(directory, options = {}) {
6176
6207
  } finally {
6177
6208
  clearTimeout(timer);
6178
6209
  }
6179
- reportContent = `# Post-Mortem Report: ${planId}
6210
+ reportContent = `# Post-Mortem Report: ${effectivePlanId}
6180
6211
  Generated: ${new Date().toISOString()}
6181
6212
 
6182
6213
  ${llmOutput}`;
6183
6214
  } catch (err) {
6184
6215
  const msg = err instanceof Error ? err.message : String(err);
6185
6216
  warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
6186
- reportContent = _internals13.buildDataOnlyReport(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6217
+ reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6187
6218
  }
6188
6219
  } else {
6189
- reportContent = _internals13.buildDataOnlyReport(planId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6220
+ reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6190
6221
  }
6191
6222
  try {
6192
6223
  const { mkdirSync: mkdirSync6 } = await import("fs");
@@ -6196,7 +6227,7 @@ ${llmOutput}`;
6196
6227
  const msg = err instanceof Error ? err.message : String(err);
6197
6228
  return {
6198
6229
  success: false,
6199
- planId,
6230
+ planId: effectivePlanId,
6200
6231
  reportPath: null,
6201
6232
  summary: null,
6202
6233
  warnings: [...warnings, `Failed to write report: ${msg}`]
@@ -6206,13 +6237,13 @@ ${llmOutput}`;
6206
6237
  const neverAppliedCount = knowledgeSummary.filter((e) => e.applied === 0 && e.violated === 0 && e.ignored === 0).length;
6207
6238
  const totalViolations = knowledgeSummary.reduce((s, e) => s + e.violated, 0);
6208
6239
  const summary = [
6209
- `Post-mortem for plan "${planId}": ${totalEntries} knowledge entries reviewed.`,
6240
+ `Post-mortem for plan "${effectivePlanId}": ${totalEntries} knowledge entries reviewed.`,
6210
6241
  `${neverAppliedCount} never-applied entries flagged; ${totalViolations} total violations recorded.`,
6211
6242
  `${proposals.length} pending proposals, ${unactionable.length} quarantined entries.`
6212
6243
  ].join(" ");
6213
6244
  return {
6214
6245
  success: true,
6215
- planId,
6246
+ planId: effectivePlanId,
6216
6247
  reportPath,
6217
6248
  summary,
6218
6249
  warnings
@@ -9900,6 +9931,9 @@ ${userInput}` : userInput;
9900
9931
  };
9901
9932
  }
9902
9933
 
9934
+ // src/services/skill-improver.ts
9935
+ init_logger();
9936
+
9903
9937
  // src/services/trajectory-cluster.ts
9904
9938
  import { mkdir as mkdir6, writeFile as writeFile6 } from "fs/promises";
9905
9939
  import * as path22 from "path";
@@ -10328,7 +10362,14 @@ async function gatherInventory(directory) {
10328
10362
  continue;
10329
10363
  }
10330
10364
  const fm = parseDraftFrontmatter(content);
10331
- if (!fm)
10365
+ if (!fm) {
10366
+ staleActiveSkills.push({
10367
+ slug: skill.slug,
10368
+ reasons: ["unparseable_frontmatter"]
10369
+ });
10370
+ continue;
10371
+ }
10372
+ if (fm.skillOrigin === "shim")
10332
10373
  continue;
10333
10374
  metadataReadable += 1;
10334
10375
  const reasons = [];
@@ -10476,6 +10517,59 @@ function buildLLMProposalFrame(args) {
10476
10517
  return lines.join(`
10477
10518
  `);
10478
10519
  }
10520
+ async function reconcileStaleActiveSkills(directory, options = {}) {
10521
+ const result = {
10522
+ regenerated: [],
10523
+ retired: [],
10524
+ skipped: [],
10525
+ checked: 0
10526
+ };
10527
+ let skills;
10528
+ try {
10529
+ skills = await listSkills(directory);
10530
+ } catch {
10531
+ return result;
10532
+ }
10533
+ for (const skill of skills.active) {
10534
+ let content;
10535
+ try {
10536
+ content = await readFile7(skill.path, "utf-8");
10537
+ } catch {
10538
+ continue;
10539
+ }
10540
+ const fm = parseDraftFrontmatter(content);
10541
+ if (fm?.skillOrigin === "shim") {
10542
+ result.skipped.push(skill.slug);
10543
+ continue;
10544
+ }
10545
+ const stale = !fm || fm.sourceKnowledgeIds.length === 0 || !fm.generatedAt;
10546
+ if (!stale)
10547
+ continue;
10548
+ result.checked += 1;
10549
+ if (options.dryRun) {
10550
+ result.retired.push(skill.slug);
10551
+ continue;
10552
+ }
10553
+ try {
10554
+ const regen = await _internals18.regenerateSkill(directory, skill.slug, {
10555
+ evaluate: false
10556
+ });
10557
+ if (regen.regenerated) {
10558
+ result.regenerated.push(skill.slug);
10559
+ } else if (regen.retired) {
10560
+ result.retired.push(skill.slug);
10561
+ } else {
10562
+ const retire = await retireSkill(directory, skill.slug, "stale_no_source_knowledge");
10563
+ if (retire.retired)
10564
+ result.retired.push(skill.slug);
10565
+ }
10566
+ } catch (err) {
10567
+ warn(`[skill-improver] reconcileStaleActiveSkills: failed to reconcile '${skill.slug}': ${err instanceof Error ? err.message : String(err)}`);
10568
+ result.skipped.push(skill.slug);
10569
+ }
10570
+ }
10571
+ return result;
10572
+ }
10479
10573
  async function runSkillImprover(req) {
10480
10574
  const cfg = req.config;
10481
10575
  const now = req.now ?? new Date;
@@ -10682,6 +10776,7 @@ async function runSkillImprover(req) {
10682
10776
  motifs: successMotifResult.motifs,
10683
10777
  proposalsWritten: successMotifResult.proposalsWritten.length
10684
10778
  };
10779
+ const staleSkillReconciliation = await reconcileStaleActiveSkills(req.directory, { dryRun: writeMode !== "draft_skills" });
10685
10780
  let autoApply;
10686
10781
  if (req.allowAutoApply !== false && delegate && req.sessionId && hasActiveFullAuto(req.sessionId)) {
10687
10782
  try {
@@ -10702,9 +10797,20 @@ async function runSkillImprover(req) {
10702
10797
  unactionableHardening,
10703
10798
  macroMotifs,
10704
10799
  successMotifs,
10800
+ staleSkillReconciliation,
10705
10801
  autoApply
10706
10802
  };
10707
10803
  }
10804
+ var _internals18 = {
10805
+ runSkillImprover,
10806
+ buildDeterministicProposal,
10807
+ buildLLMProposalFrame,
10808
+ buildSystemPrompt,
10809
+ buildUserPrompt,
10810
+ gatherInventory,
10811
+ reconcileStaleActiveSkills,
10812
+ regenerateSkill
10813
+ };
10708
10814
 
10709
10815
  // src/tools/write-retro.ts
10710
10816
  async function executeWriteRetro(args, directory) {
@@ -11048,13 +11154,13 @@ var write_retro = createSwarmTool({
11048
11154
  task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
11049
11155
  metadata: args.metadata
11050
11156
  };
11051
- return await _internals18.executeWriteRetro(writeRetroArgs, directory);
11157
+ return await _internals19.executeWriteRetro(writeRetroArgs, directory);
11052
11158
  } catch {
11053
11159
  return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
11054
11160
  }
11055
11161
  }
11056
11162
  });
11057
- var _internals18 = {
11163
+ var _internals19 = {
11058
11164
  executeWriteRetro,
11059
11165
  write_retro
11060
11166
  };
@@ -11097,8 +11203,9 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
11097
11203
  return Number.isFinite(createdAtMs) && createdAtMs >= sessionStartMs;
11098
11204
  }).length;
11099
11205
  }
11100
- async function copyDirRecursive(src, dest) {
11206
+ async function copyDirRecursiveWithFailures(src, dest) {
11101
11207
  let count = 0;
11208
+ const failures = [];
11102
11209
  const entries = await fs11.readdir(src);
11103
11210
  await fs11.mkdir(dest, { recursive: true });
11104
11211
  for (const entry of entries) {
@@ -11107,17 +11214,32 @@ async function copyDirRecursive(src, dest) {
11107
11214
  try {
11108
11215
  const stat4 = await fs11.stat(srcEntry);
11109
11216
  if (stat4.isDirectory()) {
11110
- const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
11111
- count += subCount;
11217
+ const subResult = await copyDirRecursiveWithFailures(srcEntry, destEntry);
11218
+ count += subResult.copied;
11219
+ failures.push(...subResult.failures);
11112
11220
  } else {
11113
11221
  try {
11114
11222
  await fs11.copyFile(srcEntry, destEntry);
11115
11223
  count++;
11116
- } catch {}
11224
+ } catch (err) {
11225
+ const errno = err?.code;
11226
+ if (errno !== "ENOENT") {
11227
+ failures.push(`${srcEntry}: ${err instanceof Error ? err.message : String(err)}`);
11228
+ }
11229
+ }
11117
11230
  }
11118
- } catch {}
11231
+ } catch (err) {
11232
+ const errno = err?.code;
11233
+ if (errno !== "ENOENT") {
11234
+ failures.push(`${srcEntry}: ${err instanceof Error ? err.message : String(err)}`);
11235
+ }
11236
+ }
11119
11237
  }
11120
- return count;
11238
+ return { copied: count, failures };
11239
+ }
11240
+ async function copyDirRecursive(src, dest) {
11241
+ const result = await copyDirRecursiveWithFailures(src, dest);
11242
+ return result.copied;
11121
11243
  }
11122
11244
  var ARCHIVE_ARTIFACTS = [
11123
11245
  "plan.json",
@@ -11309,8 +11431,8 @@ async function runFinalizeStage(ctx) {
11309
11431
  ];
11310
11432
  ctx.curationSucceeded = false;
11311
11433
  try {
11312
- ctx.curationResult = await _internals19.curateAndStoreSwarm(ctx.allLessons, ctx.projectName, { phase_number: 0 }, ctx.directory, ctx.config, {
11313
- llmDelegate: _internals19.createCuratorLLMDelegate(ctx.directory, "phase", ctx.options.sessionID),
11434
+ ctx.curationResult = await _internals20.curateAndStoreSwarm(ctx.allLessons, ctx.projectName, { phase_number: 0 }, ctx.directory, ctx.config, {
11435
+ llmDelegate: _internals20.createCuratorLLMDelegate(ctx.directory, "phase", ctx.options.sessionID),
11314
11436
  enrichmentQuota: {
11315
11437
  maxCalls: ctx.config.enrichment.max_calls_per_day,
11316
11438
  window: ctx.config.enrichment.quota_window
@@ -11329,7 +11451,7 @@ async function runFinalizeStage(ctx) {
11329
11451
  if (ctx.config.hive_enabled === false) {} else {
11330
11452
  try {
11331
11453
  const entries = await readKnowledge(resolveSwarmKnowledgePath(ctx.directory));
11332
- const result = await _internals19.checkHivePromotions(entries, ctx.config);
11454
+ const result = await _internals20.checkHivePromotions(entries, ctx.config);
11333
11455
  ctx.hivePromoted = result.new_promotions;
11334
11456
  } catch (hiveErr) {
11335
11457
  const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
@@ -11350,7 +11472,7 @@ async function runFinalizeStage(ctx) {
11350
11472
  ctx.knowledgeSkillHint = ctx.sessionKnowledgeCreated > 0 ? `${ctx.sessionKnowledgeCreated} knowledge entries created this session. Consider running skill_improve or skill_generate to compile mature entries into skills.` : "";
11351
11473
  if (ctx.runSkillReview) {
11352
11474
  try {
11353
- const { config: loadedConfig } = _internals19.loadPluginConfigWithMeta(ctx.directory);
11475
+ const { config: loadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
11354
11476
  const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
11355
11477
  const skillReviewResult = await runAbortableSkillReview({
11356
11478
  directory: ctx.directory,
@@ -11401,7 +11523,7 @@ async function runFinalizeStage(ctx) {
11401
11523
  }
11402
11524
  if (!ctx.planAlreadyDone || ctx.guaranteeResult.closedPhaseIds.length > 0 || ctx.guaranteeResult.closedTaskIds.length > 0) {
11403
11525
  try {
11404
- await _internals19.closePlanTerminalState(ctx.directory, ctx.planData, {
11526
+ await _internals20.closePlanTerminalState(ctx.directory, ctx.planData, {
11405
11527
  closedPhaseIds: ctx.guaranteeResult.closedPhaseIds,
11406
11528
  closedTaskIds: ctx.guaranteeResult.closedTaskIds,
11407
11529
  originalStatuses: ctx.originalStatuses
@@ -11418,11 +11540,11 @@ async function runFinalizeStage(ctx) {
11418
11540
  }
11419
11541
  try {
11420
11542
  const { CuratorConfigSchema: CCS } = await import("./schema-84146tvk.js");
11421
- const { config: pmLoadedConfig } = _internals19.loadPluginConfigWithMeta(ctx.directory);
11543
+ const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
11422
11544
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
11423
11545
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
11424
- const pmResult = await _internals19.runCuratorPostMortem(ctx.directory, {
11425
- llmDelegate: _internals19.createCuratorLLMDelegate(ctx.directory, "postmortem", ctx.options.sessionID)
11546
+ const pmResult = await _internals20.runCuratorPostMortem(ctx.directory, {
11547
+ llmDelegate: _internals20.createCuratorLLMDelegate(ctx.directory, "postmortem", ctx.options.sessionID)
11426
11548
  });
11427
11549
  if (pmResult.success && pmResult.summary) {
11428
11550
  ctx.postMortemSummary = pmResult.summary;
@@ -11436,31 +11558,145 @@ async function runFinalizeStage(ctx) {
11436
11558
  ctx.warnings.push(`Post-mortem failed: ${msg}`);
11437
11559
  }
11438
11560
  }
11561
+ async function copySqliteSafe(srcPath, destPath) {
11562
+ if (!fsSync2.existsSync(srcPath)) {
11563
+ return {
11564
+ success: true,
11565
+ skipped: true,
11566
+ reason: "source does not exist (ENOENT)"
11567
+ };
11568
+ }
11569
+ let checkpointVerified = false;
11570
+ try {
11571
+ const result = spawnSync5("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
11572
+ cwd: path24.dirname(srcPath),
11573
+ encoding: "utf-8",
11574
+ stdio: ["ignore", "pipe", "pipe"],
11575
+ timeout: 1e4,
11576
+ windowsHide: true,
11577
+ maxBuffer: 1024
11578
+ });
11579
+ if (result.error) {
11580
+ const code = result.error.code;
11581
+ if (code === "ENOENT") {
11582
+ try {
11583
+ await fs11.copyFile(srcPath, destPath);
11584
+ return {
11585
+ success: true,
11586
+ reason: "copied without WAL checkpoint (sqlite3 CLI unavailable)"
11587
+ };
11588
+ } catch (copyErr) {
11589
+ return {
11590
+ success: false,
11591
+ reason: `fallback copy failed: ${copyErr instanceof Error ? copyErr.message : String(copyErr)}`
11592
+ };
11593
+ }
11594
+ }
11595
+ return {
11596
+ success: false,
11597
+ reason: `wal_checkpoint failed: ${result.error instanceof Error ? result.error.message : String(result.error)}`
11598
+ };
11599
+ }
11600
+ if (result.status !== 0) {
11601
+ return {
11602
+ success: false,
11603
+ reason: `wal_checkpoint exited with code ${result.status}`
11604
+ };
11605
+ }
11606
+ const output = (result.stdout || "").trim();
11607
+ const lines = output.split(`
11608
+ `).filter((l) => l.trim());
11609
+ if (lines.length >= 1) {
11610
+ const dataLine = lines[0];
11611
+ const columns = dataLine.split("|");
11612
+ const busyFlag = parseInt(columns[0], 10);
11613
+ checkpointVerified = !Number.isNaN(busyFlag) && busyFlag === 0;
11614
+ }
11615
+ } catch (err) {
11616
+ return {
11617
+ success: false,
11618
+ reason: `wal_checkpoint error: ${err instanceof Error ? err.message : String(err)}`
11619
+ };
11620
+ }
11621
+ try {
11622
+ await fs11.copyFile(srcPath, destPath);
11623
+ if (checkpointVerified) {
11624
+ return { success: true };
11625
+ }
11626
+ return {
11627
+ success: true,
11628
+ reason: "WAL checkpoint incomplete (busy) \u2014 archive copy may be stale, original preserved"
11629
+ };
11630
+ } catch (err) {
11631
+ return {
11632
+ success: false,
11633
+ reason: `copy failed: ${err instanceof Error ? err.message : String(err)}`
11634
+ };
11635
+ }
11636
+ }
11439
11637
  async function runArchiveStage(ctx) {
11440
11638
  ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
11441
11639
  ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
11442
11640
  ctx.archiveDir = path24.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
11443
11641
  try {
11444
11642
  await fs11.mkdir(ctx.archiveDir, { recursive: true });
11643
+ const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
11445
11644
  for (const artifact of ARCHIVE_ARTIFACTS) {
11645
+ if (WAL_SIDECAR_FILES.has(artifact)) {
11646
+ continue;
11647
+ }
11446
11648
  const srcPath = path24.join(ctx.swarmDir, artifact);
11447
11649
  const destPath = path24.join(ctx.archiveDir, artifact);
11448
- try {
11449
- await fs11.copyFile(srcPath, destPath);
11450
- ctx.archivedFileCount++;
11451
- if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
11452
- ctx.archivedActiveStateFiles.add(artifact);
11650
+ if (artifact === "swarm.db") {
11651
+ const result = await copySqliteSafe(srcPath, destPath);
11652
+ if (result.skipped) {} else if (result.success) {
11653
+ ctx.archivedFileCount++;
11654
+ if (result.reason) {
11655
+ ctx.warnings.push(`Archived ${artifact}: ${result.reason}. Original preserved to prevent data loss.`);
11656
+ } else {
11657
+ ctx.archivedActiveStateFiles.add(artifact);
11658
+ }
11659
+ } else {
11660
+ ctx.archiveFailureReasons.set(artifact, result.reason);
11661
+ ctx.warnings.push(`Failed to archive ${artifact}: ${result.reason}. File preserved (not cleaned up).`);
11453
11662
  }
11454
- } catch {}
11663
+ } else {
11664
+ try {
11665
+ await fs11.copyFile(srcPath, destPath);
11666
+ ctx.archivedFileCount++;
11667
+ if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
11668
+ ctx.archivedActiveStateFiles.add(artifact);
11669
+ }
11670
+ } catch (err) {
11671
+ const errno = err?.code;
11672
+ if (errno === "ENOENT") {} else {
11673
+ const reason = err instanceof Error ? err.message : String(err);
11674
+ ctx.archiveFailureReasons.set(artifact, `${errno ?? "unknown"}: ${reason}`);
11675
+ ctx.warnings.push(`Failed to archive ${artifact} [${errno ?? "unknown"}]: ${reason}. File preserved (not cleaned up).`);
11676
+ }
11677
+ }
11678
+ }
11455
11679
  }
11456
11680
  for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
11457
11681
  const srcDir = path24.join(ctx.swarmDir, dirName);
11458
11682
  const destDir = path24.join(ctx.archiveDir, dirName);
11459
11683
  try {
11460
- const copied = await copyDirRecursive(srcDir, destDir);
11461
- ctx.archivedFileCount += copied;
11462
- ctx.archivedActiveStateDirs.add(dirName);
11463
- } catch {}
11684
+ const result = await copyDirRecursiveWithFailures(srcDir, destDir);
11685
+ ctx.archivedFileCount += result.copied;
11686
+ if (result.failures.length === 0) {
11687
+ ctx.archivedActiveStateDirs.add(dirName);
11688
+ } else {
11689
+ ctx.warnings.push(`Directory ${dirName} not fully archived (${result.failures.length} failure(s)). Source preserved.`);
11690
+ for (const failure of result.failures) {
11691
+ ctx.warnings.push(` - ${failure}`);
11692
+ }
11693
+ }
11694
+ } catch (err) {
11695
+ const code = err.code;
11696
+ if (code !== "ENOENT") {
11697
+ ctx.warnings.push(`Failed to archive directory ${dirName} [${code ?? "unknown"}]: ${err.message}. Source preserved.`);
11698
+ }
11699
+ }
11464
11700
  }
11465
11701
  ctx.archiveResult = `Archived ${ctx.archivedFileCount} artifact(s) to .swarm/archive/swarm-${ctx.timestamp}-${ctx.archiveSuffix}/`;
11466
11702
  } catch (archiveError) {
@@ -11478,7 +11714,7 @@ async function runArchiveEvidenceRetention(ctx) {
11478
11714
  let maxAgeDays = 30;
11479
11715
  let maxBundles = 10;
11480
11716
  try {
11481
- const { config: evidenceLoadedConfig } = _internals19.loadPluginConfigWithMeta(ctx.directory);
11717
+ const { config: evidenceLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
11482
11718
  const evidenceCfg = evidenceLoadedConfig.evidence ?? {};
11483
11719
  if (typeof evidenceCfg.max_age_days === "number") {
11484
11720
  maxAgeDays = evidenceCfg.max_age_days;
@@ -11488,7 +11724,7 @@ async function runArchiveEvidenceRetention(ctx) {
11488
11724
  }
11489
11725
  } catch {}
11490
11726
  try {
11491
- await _internals19.archiveEvidence(ctx.directory, maxAgeDays, maxBundles);
11727
+ await _internals20.archiveEvidence(ctx.directory, maxAgeDays, maxBundles);
11492
11728
  } catch (error2) {
11493
11729
  const msg = error2 instanceof Error ? error2.message : String(error2);
11494
11730
  ctx.warnings.push(`Evidence retention archive failed: ${msg}`);
@@ -11501,14 +11737,21 @@ async function runCleanStage(ctx) {
11501
11737
  if (ctx.archivedActiveStateFiles.size > 0) {
11502
11738
  for (const artifact of ACTIVE_STATE_TO_CLEAN) {
11503
11739
  if (!ctx.archivedActiveStateFiles.has(artifact)) {
11504
- ctx.warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
11740
+ const reason = ctx.archiveFailureReasons?.get(artifact);
11741
+ ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
11505
11742
  continue;
11506
11743
  }
11507
11744
  const filePath = path24.join(ctx.swarmDir, artifact);
11508
11745
  try {
11509
11746
  await fs11.unlink(filePath);
11510
11747
  cleanedFiles.push(artifact);
11511
- } catch {}
11748
+ } catch (err) {
11749
+ const errno = err?.code;
11750
+ if (errno === "ENOENT") {} else {
11751
+ const reason = err instanceof Error ? err.message : String(err);
11752
+ ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno ?? "unknown"}]: ${reason}`);
11753
+ }
11754
+ }
11512
11755
  }
11513
11756
  } else {
11514
11757
  ctx.warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
@@ -11530,15 +11773,33 @@ async function runCleanStage(ctx) {
11530
11773
  try {
11531
11774
  await fs11.unlink(path24.join(ctx.swarmDir, backup));
11532
11775
  configBackupsRemoved++;
11533
- } catch {}
11776
+ } catch (err) {
11777
+ const errno = err?.code;
11778
+ if (errno === "ENOENT") {} else {
11779
+ const reason = err instanceof Error ? err.message : String(err);
11780
+ ctx.warnings.push(`Failed to clean config-backup ${backup} [${errno ?? "unknown"}]: ${reason}`);
11781
+ }
11782
+ }
11534
11783
  }
11535
11784
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
11536
11785
  for (const sibling of ledgerSiblings) {
11537
11786
  try {
11538
11787
  await fs11.unlink(path24.join(ctx.swarmDir, sibling));
11539
- } catch {}
11788
+ } catch (err) {
11789
+ const errno = err?.code;
11790
+ if (errno === "ENOENT") {} else {
11791
+ const reason = err instanceof Error ? err.message : String(err);
11792
+ ctx.warnings.push(`Failed to clean ledger sibling ${sibling} [${errno ?? "unknown"}]: ${reason}`);
11793
+ }
11794
+ }
11540
11795
  }
11541
- } catch {}
11796
+ } catch (err) {
11797
+ const errno = err?.code;
11798
+ if (errno === "ENOENT") {} else {
11799
+ const reason = err instanceof Error ? err.message : String(err);
11800
+ ctx.warnings.push(`Failed to read ${ctx.swarmDir} for stale-file cleanup [${errno ?? "unknown"}]: ${reason}`);
11801
+ }
11802
+ }
11542
11803
  let swarmPlanFilesRemoved = 0;
11543
11804
  const candidates = [
11544
11805
  path24.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
@@ -11564,9 +11825,21 @@ async function runCleanStage(ctx) {
11564
11825
  try {
11565
11826
  await fs11.unlink(path24.join(ctx.swarmDir, tmp));
11566
11827
  tmpFilesRemoved++;
11567
- } catch {}
11828
+ } catch (err) {
11829
+ const errno = err?.code;
11830
+ if (errno === "ENOENT") {} else {
11831
+ const reason = err instanceof Error ? err.message : String(err);
11832
+ ctx.warnings.push(`Failed to clean tmp file ${tmp} [${errno ?? "unknown"}]: ${reason}`);
11833
+ }
11834
+ }
11568
11835
  }
11569
- } catch {}
11836
+ } catch (err) {
11837
+ const errno = err?.code;
11838
+ if (errno === "ENOENT") {} else {
11839
+ const reason = err instanceof Error ? err.message : String(err);
11840
+ ctx.warnings.push(`Failed to read ${ctx.swarmDir} for tmp-file cleanup [${errno ?? "unknown"}]: ${reason}`);
11841
+ }
11842
+ }
11570
11843
  if (tmpFilesRemoved > 0) {
11571
11844
  cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
11572
11845
  }
@@ -11583,9 +11856,14 @@ async function runCleanStage(ctx) {
11583
11856
  ""
11584
11857
  ].join(`
11585
11858
  `);
11859
+ const contextTempPath = path24.join(path24.dirname(contextPath), `${path24.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
11586
11860
  try {
11587
- await fs11.writeFile(contextPath, contextContent, "utf-8");
11861
+ await fs11.writeFile(contextTempPath, contextContent, "utf-8");
11862
+ fsSync2.renameSync(contextTempPath, contextPath);
11588
11863
  } catch (error2) {
11864
+ try {
11865
+ fsSync2.unlinkSync(contextTempPath);
11866
+ } catch {}
11589
11867
  const msg = error2 instanceof Error ? error2.message : String(error2);
11590
11868
  ctx.warnings.push(`Failed to reset context.md: ${msg}`);
11591
11869
  console.warn("[close-command] Failed to write context.md:", error2);
@@ -11601,9 +11879,9 @@ async function runAlignStage(ctx) {
11601
11879
  const pruneBranches = ctx.args.includes("--prune-branches");
11602
11880
  let gitAlignResult = "";
11603
11881
  const prunedBranches = [];
11604
- const gitStatus = _internals19.getGitRepositoryStatus(ctx.directory);
11882
+ const gitStatus = _internals20.getGitRepositoryStatus(ctx.directory);
11605
11883
  if (gitStatus.isRepo) {
11606
- const aggressiveResult = await _internals19.resetToMainAfterMerge(ctx.directory, {
11884
+ const aggressiveResult = await _internals20.resetToMainAfterMerge(ctx.directory, {
11607
11885
  pruneBranches
11608
11886
  });
11609
11887
  if (aggressiveResult.success) {
@@ -11615,7 +11893,7 @@ async function runAlignStage(ctx) {
11615
11893
  ctx.warnings.push("Uncommitted changes were discarded during git alignment");
11616
11894
  }
11617
11895
  } else {
11618
- const alignResult = await _internals19.resetToRemoteBranch(ctx.directory, {
11896
+ const alignResult = await _internals20.resetToRemoteBranch(ctx.directory, {
11619
11897
  pruneBranches
11620
11898
  });
11621
11899
  gitAlignResult = alignResult.message;
@@ -11675,20 +11953,38 @@ async function handleCloseCommand(directory, args, options = {}) {
11675
11953
  let finalizeLock = {
11676
11954
  acquired: false
11677
11955
  };
11678
- finalizeLock = await _internals19.acquireFinalizeLock(directory);
11956
+ finalizeLock = await _internals20.acquireFinalizeLock(directory);
11679
11957
  if (!finalizeLock.acquired) {
11680
11958
  return `\u274C 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.`;
11681
11959
  }
11682
- const phases = planData.phases ?? [];
11683
- const inProgressPhases = phases.filter((p) => p.status === "in_progress");
11684
- const isForced = args.includes("--force");
11685
- const runSkillReview = args.includes("--skill-review");
11686
- let planAlreadyDone = false;
11687
- if (planExists) {
11688
- planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
11689
- }
11690
11960
  try {
11691
- const { config: loadedConfig } = _internals19.loadPluginConfigWithMeta(directory);
11961
+ if (!planExists) {
11962
+ const archiveDir = path24.join(swarmDir, "archive");
11963
+ try {
11964
+ const archiveEntries = await fs11.readdir(archiveDir);
11965
+ const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
11966
+ if (hasArchiveBundle) {
11967
+ const hasActiveState = [
11968
+ ...ACTIVE_STATE_TO_CLEAN,
11969
+ ...ACTIVE_STATE_DIRS_TO_CLEAN
11970
+ ].some((entry) => fsSync2.existsSync(path24.join(swarmDir, entry)));
11971
+ if (!hasActiveState) {
11972
+ return `\u2705 Already finalized \u2014 nothing to do.
11973
+
11974
+ This project was already finalized in a previous /swarm close run. The plan has been archived and cleaned up. No further action is needed.`;
11975
+ }
11976
+ }
11977
+ } catch {}
11978
+ }
11979
+ const phases = planData.phases ?? [];
11980
+ const inProgressPhases = phases.filter((p) => p.status === "in_progress");
11981
+ const isForced = args.includes("--force");
11982
+ const runSkillReview = args.includes("--skill-review");
11983
+ let planAlreadyDone = false;
11984
+ if (planExists) {
11985
+ planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
11986
+ }
11987
+ const { config: loadedConfig } = _internals20.loadPluginConfigWithMeta(directory);
11692
11988
  const config = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
11693
11989
  const ctx = {
11694
11990
  directory,
@@ -11724,6 +12020,7 @@ async function handleCloseCommand(directory, args, options = {}) {
11724
12020
  archivedFileCount: 0,
11725
12021
  archivedActiveStateFiles: new Set,
11726
12022
  archivedActiveStateDirs: new Set,
12023
+ archiveFailureReasons: new Map,
11727
12024
  timestamp: "",
11728
12025
  archiveDir: "",
11729
12026
  archiveSuffix: "",
@@ -11786,14 +12083,19 @@ async function handleCloseCommand(directory, args, options = {}) {
11786
12083
  ...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
11787
12084
  ].join(`
11788
12085
  `);
12086
+ const closeSummaryTempPath = path24.join(path24.dirname(closeSummaryPath), `${path24.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
11789
12087
  try {
11790
- await fs11.writeFile(closeSummaryPath, summaryContent, "utf-8");
12088
+ await fs11.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
12089
+ fsSync2.renameSync(closeSummaryTempPath, closeSummaryPath);
11791
12090
  } catch (error2) {
12091
+ try {
12092
+ fsSync2.unlinkSync(closeSummaryTempPath);
12093
+ } catch {}
11792
12094
  const msg = error2 instanceof Error ? error2.message : String(error2);
11793
12095
  ctx.warnings.push(`Failed to write close-summary.md: ${msg}`);
11794
12096
  console.warn("[close-command] Failed to write close-summary.md:", error2);
11795
12097
  }
11796
- _internals19.resetSwarmStatePreservingSingletons();
12098
+ _internals20.resetSwarmStatePreservingSingletons();
11797
12099
  const retroWarnings = ctx.warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
11798
12100
  const otherWarnings = ctx.warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
11799
12101
  let warningMsg = "";
@@ -11848,7 +12150,7 @@ async function acquireFinalizeLock(directory) {
11848
12150
  }
11849
12151
  return { acquired: false };
11850
12152
  }
11851
- var _internals19 = {
12153
+ var _internals20 = {
11852
12154
  ACTIVE_STATE_DIRS_TO_CLEAN,
11853
12155
  countSessionKnowledgeEntries,
11854
12156
  CLOSE_SKILL_REVIEW_TIMEOUT_MS,
@@ -12129,7 +12431,7 @@ async function handleConfigCommand(directory, _args) {
12129
12431
  }
12130
12432
 
12131
12433
  // src/services/skill-consolidation.ts
12132
- import { existsSync as existsSync13 } from "fs";
12434
+ import { existsSync as existsSync14 } from "fs";
12133
12435
  import { mkdir as mkdir8, readFile as readFile8, rename as rename4, writeFile as writeFile8 } from "fs/promises";
12134
12436
  import * as path26 from "path";
12135
12437
 
@@ -12160,7 +12462,7 @@ function consolidationStatePath(directory) {
12160
12462
  }
12161
12463
  async function readState2(directory) {
12162
12464
  const filePath = consolidationStatePath(directory);
12163
- if (!existsSync13(filePath))
12465
+ if (!existsSync14(filePath))
12164
12466
  return {};
12165
12467
  try {
12166
12468
  const parsed = JSON.parse(await readFile8(filePath, "utf-8"));
@@ -12636,9 +12938,9 @@ async function detectDarkMatter(directory, options) {
12636
12938
  } catch {
12637
12939
  return [];
12638
12940
  }
12639
- const commitMap = await _internals20.parseGitLog(directory, maxCommitsToAnalyze);
12640
- const matrix = _internals20.buildCoChangeMatrix(commitMap, maxFilesPerCommit);
12641
- const staticEdges = await _internals20.getStaticEdges(directory);
12941
+ const commitMap = await _internals21.parseGitLog(directory, maxCommitsToAnalyze);
12942
+ const matrix = _internals21.buildCoChangeMatrix(commitMap, maxFilesPerCommit);
12943
+ const staticEdges = await _internals21.getStaticEdges(directory);
12642
12944
  const results = [];
12643
12945
  for (const entry of matrix.values()) {
12644
12946
  const key = `${entry.fileA}::${entry.fileB}`;
@@ -12754,11 +13056,11 @@ var co_change_analyzer = createSwarmTool({
12754
13056
  npmiThreshold,
12755
13057
  maxCommitsToAnalyze
12756
13058
  };
12757
- const pairs = await _internals20.detectDarkMatter(directory, options);
12758
- return _internals20.formatDarkMatterOutput(pairs);
13059
+ const pairs = await _internals21.detectDarkMatter(directory, options);
13060
+ return _internals21.formatDarkMatterOutput(pairs);
12759
13061
  }
12760
13062
  });
12761
- var _internals20 = {
13063
+ var _internals21 = {
12762
13064
  parseGitLog,
12763
13065
  buildCoChangeMatrix,
12764
13066
  getStaticEdges,
@@ -12775,7 +13077,7 @@ var DEFAULT_MAX_COMMITS = 500;
12775
13077
  var cache = new Map;
12776
13078
  async function readGitHead(directory) {
12777
13079
  try {
12778
- const { stdout } = await _internals21.execFile("git", ["rev-parse", "HEAD"], {
13080
+ const { stdout } = await _internals22.execFile("git", ["rev-parse", "HEAD"], {
12779
13081
  cwd: directory,
12780
13082
  timeout: GIT_HEAD_TIMEOUT_MS
12781
13083
  });
@@ -12801,9 +13103,9 @@ async function getCoChangeData(directory, options) {
12801
13103
  let entries;
12802
13104
  let commitsObserved;
12803
13105
  try {
12804
- const commitMap = await _internals21.parseGitLog(directory, maxCommits);
13106
+ const commitMap = await _internals22.parseGitLog(directory, maxCommits);
12805
13107
  commitsObserved = commitMap.size;
12806
- const matrix = _internals21.buildCoChangeMatrix(commitMap);
13108
+ const matrix = _internals22.buildCoChangeMatrix(commitMap);
12807
13109
  entries = Array.from(matrix.values());
12808
13110
  } catch {
12809
13111
  return { pairs: [], commitsObserved: 0 };
@@ -12827,10 +13129,10 @@ async function getCoChangePairs(directory, options) {
12827
13129
  const data = await getCoChangeData(directory, options);
12828
13130
  return data.pairs;
12829
13131
  }
12830
- var _internals21 = {
13132
+ var _internals22 = {
12831
13133
  execFile: execFileAsync,
12832
- parseGitLog: _internals20.parseGitLog,
12833
- buildCoChangeMatrix: _internals20.buildCoChangeMatrix
13134
+ parseGitLog: _internals21.parseGitLog,
13135
+ buildCoChangeMatrix: _internals21.buildCoChangeMatrix
12834
13136
  };
12835
13137
 
12836
13138
  // src/turbo/epic/cochange-conflict.ts
@@ -13112,7 +13414,7 @@ async function handleCouplingCommand(directory, args) {
13112
13414
 
13113
13415
  Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>] [--format markdown|json] [--persist]`;
13114
13416
  }
13115
- const plan = await _internals22.loadPlanJsonOnly(directory);
13417
+ const plan = await _internals23.loadPlanJsonOnly(directory);
13116
13418
  if (plan === null) {
13117
13419
  return "No plan found at `.swarm/plan.json`. Run `/swarm plan` to create one before measuring coupling.";
13118
13420
  }
@@ -13136,7 +13438,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
13136
13438
  const scope = scopeFiles ?? task.files_touched ?? [];
13137
13439
  return { id: task.id, scope };
13138
13440
  });
13139
- const cochangePairs = await _internals22.getCoChangePairs(directory);
13441
+ const cochangePairs = await _internals23.getCoChangePairs(directory);
13140
13442
  const report = computeCouplingReport(tasks, cochangePairs, {
13141
13443
  npmi: parsed.threshold,
13142
13444
  minCoChanges: parsed.minCoChanges
@@ -13175,7 +13477,7 @@ _Warning: failed to persist report (${persistStatus.error})._`;
13175
13477
  }
13176
13478
  return `${formatCouplingReportMarkdown(report)}${persistTrailer}`;
13177
13479
  }
13178
- var _internals22 = {
13480
+ var _internals23 = {
13179
13481
  loadPlanJsonOnly,
13180
13482
  getCoChangePairs
13181
13483
  };
@@ -13229,7 +13531,7 @@ async function handleDarkMatterCommand(directory, args) {
13229
13531
  }
13230
13532
  let pairs;
13231
13533
  try {
13232
- pairs = await _internals20.detectDarkMatter(directory, options);
13534
+ pairs = await _internals21.detectDarkMatter(directory, options);
13233
13535
  } catch (err) {
13234
13536
  const errMsg = err instanceof Error ? err.message : String(err);
13235
13537
  return `## Dark Matter Analysis Failed
@@ -13607,7 +13909,7 @@ ${USAGE5}`;
13607
13909
 
13608
13910
  // src/services/diagnose-service.ts
13609
13911
  import * as child_process4 from "child_process";
13610
- import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync6 } from "fs";
13912
+ import { existsSync as existsSync17, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync6 } from "fs";
13611
13913
  import path31 from "path";
13612
13914
  import { fileURLToPath } from "url";
13613
13915
 
@@ -13660,11 +13962,11 @@ init_capability_probe();
13660
13962
  init_executor();
13661
13963
 
13662
13964
  // src/services/knowledge-diagnostics.ts
13663
- import { existsSync as existsSync15 } from "fs";
13965
+ import { existsSync as existsSync16 } from "fs";
13664
13966
  import { readFile as readFile10 } from "fs/promises";
13665
13967
 
13666
13968
  // src/services/version-check.ts
13667
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
13969
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
13668
13970
  import { homedir as homedir4 } from "os";
13669
13971
  import { join as join25 } from "path";
13670
13972
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
@@ -13679,7 +13981,7 @@ function cacheFile() {
13679
13981
  function readVersionCache() {
13680
13982
  try {
13681
13983
  const path31 = cacheFile();
13682
- if (!existsSync14(path31))
13984
+ if (!existsSync15(path31))
13683
13985
  return null;
13684
13986
  const raw = readFileSync8(path31, "utf-8");
13685
13987
  const parsed = JSON.parse(raw);
@@ -13720,7 +14022,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
13720
14022
  var UNACTIONABLE_BACKLOG_WARN = 100;
13721
14023
  var INSIGHT_BACKLOG_WARN = 50;
13722
14024
  async function readRawLines(filePath) {
13723
- if (!existsSync15(filePath))
14025
+ if (!existsSync16(filePath))
13724
14026
  return { entries: [], corrupt: 0 };
13725
14027
  const content = await readFile10(filePath, "utf-8");
13726
14028
  const entries = [];
@@ -13845,7 +14147,7 @@ async function computeKnowledgeDebug(directory) {
13845
14147
  };
13846
14148
  }
13847
14149
  async function safeJsonlCount(filePath) {
13848
- if (!filePath || !existsSync15(filePath))
14150
+ if (!filePath || !existsSync16(filePath))
13849
14151
  return 0;
13850
14152
  try {
13851
14153
  const content = await readFile10(filePath, "utf-8");
@@ -13917,7 +14219,7 @@ async function checkKnowledgeHealth(directory) {
13917
14219
  // src/services/diagnose-service.ts
13918
14220
  var { version: version2 } = package_default;
13919
14221
  var sandboxCapabilityProbe = new SandboxCapabilityProbe;
13920
- var _internals23 = {
14222
+ var _internals24 = {
13921
14223
  detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
13922
14224
  getSandboxExecutor: getExecutor
13923
14225
  };
@@ -14166,7 +14468,7 @@ async function checkConfigBackups(directory) {
14166
14468
  }
14167
14469
  async function checkGitRepository(directory) {
14168
14470
  try {
14169
- if (!existsSync16(directory) || !statSync6(directory).isDirectory()) {
14471
+ if (!existsSync17(directory) || !statSync6(directory).isDirectory()) {
14170
14472
  return {
14171
14473
  name: "Git Repository",
14172
14474
  status: "\u274C",
@@ -14231,7 +14533,7 @@ async function checkSpecStaleness(directory, plan) {
14231
14533
  }
14232
14534
  async function checkConfigParseability(directory) {
14233
14535
  const configPath = path31.join(directory, ".opencode/opencode-swarm.json");
14234
- if (!existsSync16(configPath)) {
14536
+ if (!existsSync17(configPath)) {
14235
14537
  return {
14236
14538
  name: "Config Parseability",
14237
14539
  status: "\u2705",
@@ -14286,11 +14588,11 @@ async function checkGrammarWasmFiles() {
14286
14588
  const thisDir = path31.dirname(fileURLToPath(import.meta.url));
14287
14589
  const grammarDir = resolveGrammarDir(thisDir);
14288
14590
  const missing = [];
14289
- if (!existsSync16(path31.join(grammarDir, "tree-sitter.wasm"))) {
14591
+ if (!existsSync17(path31.join(grammarDir, "tree-sitter.wasm"))) {
14290
14592
  missing.push("tree-sitter.wasm (core runtime)");
14291
14593
  }
14292
14594
  for (const file of grammarFiles) {
14293
- if (!existsSync16(path31.join(grammarDir, file))) {
14595
+ if (!existsSync17(path31.join(grammarDir, file))) {
14294
14596
  missing.push(file);
14295
14597
  }
14296
14598
  }
@@ -14309,7 +14611,7 @@ async function checkGrammarWasmFiles() {
14309
14611
  }
14310
14612
  async function checkCheckpointManifest(directory) {
14311
14613
  const manifestPath = path31.join(directory, ".swarm/checkpoints.json");
14312
- if (!existsSync16(manifestPath)) {
14614
+ if (!existsSync17(manifestPath)) {
14313
14615
  return {
14314
14616
  name: "Checkpoint Manifest",
14315
14617
  status: "\u2705",
@@ -14361,7 +14663,7 @@ async function checkCheckpointManifest(directory) {
14361
14663
  }
14362
14664
  async function checkEventStreamIntegrity(directory) {
14363
14665
  const eventsPath = path31.join(directory, ".swarm/events.jsonl");
14364
- if (!existsSync16(eventsPath)) {
14666
+ if (!existsSync17(eventsPath)) {
14365
14667
  return {
14366
14668
  name: "Event Stream",
14367
14669
  status: "\u2705",
@@ -14402,7 +14704,7 @@ async function checkEventStreamIntegrity(directory) {
14402
14704
  }
14403
14705
  async function checkSteeringDirectives(directory) {
14404
14706
  const eventsPath = path31.join(directory, ".swarm/events.jsonl");
14405
- if (!existsSync16(eventsPath)) {
14707
+ if (!existsSync17(eventsPath)) {
14406
14708
  return {
14407
14709
  name: "Steering Directives",
14408
14710
  status: "\u2705",
@@ -14458,7 +14760,7 @@ async function checkCurator(directory) {
14458
14760
  };
14459
14761
  }
14460
14762
  const summaryPath = path31.join(directory, ".swarm/curator-summary.json");
14461
- if (!existsSync16(summaryPath)) {
14763
+ if (!existsSync17(summaryPath)) {
14462
14764
  return {
14463
14765
  name: "Curator",
14464
14766
  status: "\u2705",
@@ -14501,9 +14803,9 @@ async function checkCurator(directory) {
14501
14803
  }
14502
14804
  async function getSandboxStatus() {
14503
14805
  try {
14504
- const capability = await _internals23.detectSandboxCapability();
14806
+ const capability = await _internals24.detectSandboxCapability();
14505
14807
  const mechanism = capability.mechanism ?? "none";
14506
- const executor = await _internals23.getSandboxExecutor();
14808
+ const executor = await _internals24.getSandboxExecutor();
14507
14809
  const hasExecutor = executor !== null;
14508
14810
  if (hasExecutor) {
14509
14811
  return {
@@ -14660,7 +14962,7 @@ async function getDiagnoseData(directory) {
14660
14962
  checks.push(await checkKnowledgeHealth(directory));
14661
14963
  try {
14662
14964
  const evidenceDir = path31.join(directory, ".swarm", "evidence");
14663
- const snapshotFiles = existsSync16(evidenceDir) ? readdirSync3(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
14965
+ const snapshotFiles = existsSync17(evidenceDir) ? readdirSync3(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
14664
14966
  if (snapshotFiles.length > 0) {
14665
14967
  const latest = snapshotFiles.sort().pop();
14666
14968
  checks.push({
@@ -14693,7 +14995,7 @@ async function getDiagnoseData(directory) {
14693
14995
  const cacheRows = [];
14694
14996
  for (const cachePath of cachePaths) {
14695
14997
  try {
14696
- if (!existsSync16(cachePath)) {
14998
+ if (!existsSync17(cachePath)) {
14697
14999
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
14698
15000
  continue;
14699
15001
  }
@@ -15239,7 +15541,7 @@ function readPromotionEvidence(directory) {
15239
15541
  }
15240
15542
 
15241
15543
  // src/commands/epic.ts
15242
- var _internals24 = {
15544
+ var _internals25 = {
15243
15545
  loadPluginConfigWithMeta,
15244
15546
  loadPlanJsonOnly,
15245
15547
  getCoChangeData,
@@ -15261,7 +15563,7 @@ async function handleEpicCommand(directory, args, sessionID) {
15261
15563
  if (!sessionID || sessionID.trim() === "") {
15262
15564
  return "Error: No active session context. Epic Mode requires an active session. Use /swarm epic from within an OpenCode session.";
15263
15565
  }
15264
- const session = _internals24.ensureAgentSession(sessionID, undefined, directory);
15566
+ const session = _internals25.ensureAgentSession(sessionID, undefined, directory);
15265
15567
  const arg0 = args[0]?.toLowerCase();
15266
15568
  switch (arg0) {
15267
15569
  case "status":
@@ -15288,7 +15590,7 @@ Usage:
15288
15590
  }
15289
15591
  function enableAndAck(directory, sessionID, session) {
15290
15592
  try {
15291
- _internals24.enableEpicMode(directory, sessionID);
15593
+ _internals25.enableEpicMode(directory, sessionID);
15292
15594
  } catch (err) {
15293
15595
  return `Error enabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
15294
15596
  }
@@ -15304,7 +15606,7 @@ function enableAndAck(directory, sessionID, session) {
15304
15606
  }
15305
15607
  function disableAndAck(directory, sessionID, session) {
15306
15608
  try {
15307
- _internals24.disableEpicMode(directory, sessionID);
15609
+ _internals25.disableEpicMode(directory, sessionID);
15308
15610
  } catch (err) {
15309
15611
  return `Error disabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
15310
15612
  }
@@ -15313,12 +15615,12 @@ function disableAndAck(directory, sessionID, session) {
15313
15615
  }
15314
15616
  function renderStatus(directory, sessionID) {
15315
15617
  const lines = ["## Epic Mode \u2014 Status", ""];
15316
- if (_internals24.isStateUnreadable(directory)) {
15618
+ if (_internals25.isStateUnreadable(directory)) {
15317
15619
  lines.push("**Epic Mode state is unreadable** (`.swarm/epic-state.json` is corrupt or has an unexpected shape). Status cannot be reported until the file is repaired or removed. The fail-closed marker means `epic_decide_phase` will refuse to compute a verdict in this state.");
15318
15620
  return lines.join(`
15319
15621
  `);
15320
15622
  }
15321
- const state = _internals24.loadEpicSessionState(directory, sessionID);
15623
+ const state = _internals25.loadEpicSessionState(directory, sessionID);
15322
15624
  if (!state) {
15323
15625
  lines.push("Epic Mode has not been toggled for this session.");
15324
15626
  return lines.join(`
@@ -15370,7 +15672,7 @@ function formatGreenfieldDetail(input) {
15370
15672
  function renderLast(directory) {
15371
15673
  let records;
15372
15674
  try {
15373
- records = _internals24.readPromotionEvidence(directory);
15675
+ records = _internals25.readPromotionEvidence(directory);
15374
15676
  } catch (err) {
15375
15677
  return `Error reading epic-promotions.jsonl: ${err instanceof Error ? err.message : String(err)}`;
15376
15678
  }
@@ -15425,7 +15727,7 @@ function renderLast(directory) {
15425
15727
  `);
15426
15728
  }
15427
15729
  function renderCalibration(directory) {
15428
- if (_internals24.isCalibrationStateUnreadable(directory)) {
15730
+ if (_internals25.isCalibrationStateUnreadable(directory)) {
15429
15731
  return [
15430
15732
  "## Epic Mode \u2014 Calibration",
15431
15733
  "",
@@ -15437,11 +15739,11 @@ function renderCalibration(directory) {
15437
15739
  }
15438
15740
  let state;
15439
15741
  try {
15440
- state = _internals24.loadCalibrationState(directory);
15742
+ state = _internals25.loadCalibrationState(directory);
15441
15743
  } catch (err) {
15442
15744
  return `Error reading calibration state: ${err instanceof Error ? err.message : String(err)}`;
15443
15745
  }
15444
- const { config } = _internals24.loadPluginConfigWithMeta(directory);
15746
+ const { config } = _internals25.loadPluginConfigWithMeta(directory);
15445
15747
  const staticThreshold = config.turbo?.epic?.mode?.activation_threshold ?? 0.3;
15446
15748
  const calibrationCfg = config.turbo?.epic?.calibration;
15447
15749
  const loosenWindow = calibrationCfg?.loosen_window ?? 10;
@@ -15489,7 +15791,7 @@ function renderCalibration(directory) {
15489
15791
  lines.push("");
15490
15792
  let recentDivergent = [];
15491
15793
  try {
15492
- const all = _internals24.readDivergenceHistory(directory, { limit: 50 });
15794
+ const all = _internals25.readDivergenceHistory(directory, { limit: 50 });
15493
15795
  recentDivergent = all.filter((r) => !r.isClean).slice(-5);
15494
15796
  } catch {}
15495
15797
  lines.push("### Recent divergent tasks (tightened the threshold)");
@@ -15506,11 +15808,11 @@ function renderCalibration(directory) {
15506
15808
  `);
15507
15809
  }
15508
15810
  async function renderDecide(directory) {
15509
- const plan = await _internals24.loadPlanJsonOnly(directory);
15811
+ const plan = await _internals25.loadPlanJsonOnly(directory);
15510
15812
  if (!plan) {
15511
15813
  return "No plan found at `.swarm/plan.json`. Run `/swarm plan` first.";
15512
15814
  }
15513
- const { config } = _internals24.loadPluginConfigWithMeta(directory);
15815
+ const { config } = _internals25.loadPluginConfigWithMeta(directory);
15514
15816
  const modeCfg = config.turbo?.epic?.mode;
15515
15817
  const cochangeCfg = config.turbo?.epic?.cochange;
15516
15818
  const activationThreshold = modeCfg?.activation_threshold ?? 0.3;
@@ -15520,20 +15822,20 @@ async function renderDecide(directory) {
15520
15822
  const tasks = [];
15521
15823
  for (const phase of plan.phases) {
15522
15824
  for (const task of phase.tasks) {
15523
- const scopeFiles = _internals24.readTaskScopes(directory, task.id);
15825
+ const scopeFiles = _internals25.readTaskScopes(directory, task.id);
15524
15826
  const scope = scopeFiles ?? task.files_touched ?? [];
15525
15827
  tasks.push({ id: task.id, scope });
15526
15828
  }
15527
15829
  }
15528
- const { pairs, commitsObserved } = await _internals24.getCoChangeData(directory);
15830
+ const { pairs, commitsObserved } = await _internals25.getCoChangeData(directory);
15529
15831
  const isGitProject = (() => {
15530
15832
  try {
15531
- return _internals24.isGitRepo(directory);
15833
+ return _internals25.isGitRepo(directory);
15532
15834
  } catch {
15533
15835
  return false;
15534
15836
  }
15535
15837
  })();
15536
- const verdict = _internals24.decideEpicActivation(tasks, pairs, commitsObserved, {
15838
+ const verdict = _internals25.decideEpicActivation(tasks, pairs, commitsObserved, {
15537
15839
  activationThreshold,
15538
15840
  minCommitsForSignal,
15539
15841
  cochangeNpmiThreshold,
@@ -15577,7 +15879,7 @@ function formatVerdict(verdict) {
15577
15879
  }
15578
15880
 
15579
15881
  // src/services/evidence-service.ts
15580
- var _internals25 = {
15882
+ var _internals26 = {
15581
15883
  loadEvidence,
15582
15884
  listEvidenceTaskIds
15583
15885
  };
@@ -15622,7 +15924,7 @@ function getVerdictEmoji(verdict) {
15622
15924
  return getVerdictIcon(verdict);
15623
15925
  }
15624
15926
  async function getTaskEvidenceData(directory, taskId) {
15625
- const result = await _internals25.loadEvidence(directory, taskId);
15927
+ const result = await _internals26.loadEvidence(directory, taskId);
15626
15928
  if (result.status !== "found") {
15627
15929
  return {
15628
15930
  hasEvidence: false,
@@ -15645,13 +15947,13 @@ async function getTaskEvidenceData(directory, taskId) {
15645
15947
  };
15646
15948
  }
15647
15949
  async function getEvidenceListData(directory) {
15648
- const taskIds = await _internals25.listEvidenceTaskIds(directory);
15950
+ const taskIds = await _internals26.listEvidenceTaskIds(directory);
15649
15951
  if (taskIds.length === 0) {
15650
15952
  return { hasEvidence: false, tasks: [] };
15651
15953
  }
15652
15954
  const tasks = [];
15653
15955
  for (const taskId of taskIds) {
15654
- const result = await _internals25.loadEvidence(directory, taskId);
15956
+ const result = await _internals26.loadEvidence(directory, taskId);
15655
15957
  if (result.status === "found") {
15656
15958
  tasks.push({
15657
15959
  taskId,
@@ -15731,7 +16033,7 @@ async function handleEvidenceCommand(directory, args) {
15731
16033
  return formatTaskEvidenceMarkdown(evidenceData);
15732
16034
  }
15733
16035
  async function handleEvidenceSummaryCommand(directory) {
15734
- const { buildEvidenceSummary } = await import("./evidence-summary-service-gg5m9z57.js");
16036
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-5me91eq8.js");
15735
16037
  const artifact = await buildEvidenceSummary(directory);
15736
16038
  if (!artifact) {
15737
16039
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -16235,7 +16537,7 @@ function buildStatusReport(directory, sessionID, sessionFlag) {
16235
16537
 
16236
16538
  // src/commands/handoff.ts
16237
16539
  import crypto4 from "crypto";
16238
- import { renameSync as renameSync8, unlinkSync as unlinkSync4 } from "fs";
16540
+ import { renameSync as renameSync9, unlinkSync as unlinkSync5 } from "fs";
16239
16541
 
16240
16542
  // src/services/handoff-service.ts
16241
16543
  var RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
@@ -16273,7 +16575,7 @@ function extractCurrentPhaseFromPlan2(plan) {
16273
16575
  if (!plan) {
16274
16576
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
16275
16577
  }
16276
- if (!_internals26.validatePlanPhases(plan)) {
16578
+ if (!_internals27.validatePlanPhases(plan)) {
16277
16579
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
16278
16580
  }
16279
16581
  let currentPhase = null;
@@ -16415,9 +16717,9 @@ function extractPhaseMetrics(content) {
16415
16717
  async function getHandoffData(directory) {
16416
16718
  const now = new Date().toISOString();
16417
16719
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
16418
- const sessionState = _internals26.parseSessionState(sessionContent);
16720
+ const sessionState = _internals27.parseSessionState(sessionContent);
16419
16721
  const plan = await loadPlanJsonOnly(directory);
16420
- const planInfo = _internals26.extractCurrentPhaseFromPlan(plan);
16722
+ const planInfo = _internals27.extractCurrentPhaseFromPlan(plan);
16421
16723
  if (!plan) {
16422
16724
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
16423
16725
  if (planMdContent) {
@@ -16436,8 +16738,8 @@ async function getHandoffData(directory) {
16436
16738
  }
16437
16739
  }
16438
16740
  const contextContent = await readSwarmFileAsync(directory, "context.md");
16439
- const recentDecisions = _internals26.extractDecisions(contextContent);
16440
- const rawPhaseMetrics = _internals26.extractPhaseMetrics(contextContent);
16741
+ const recentDecisions = _internals27.extractDecisions(contextContent);
16742
+ const rawPhaseMetrics = _internals27.extractPhaseMetrics(contextContent);
16441
16743
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
16442
16744
  let delegationState = null;
16443
16745
  if (sessionState?.delegationState) {
@@ -16601,7 +16903,7 @@ ${lines.join(`
16601
16903
  `)}
16602
16904
  \`\`\``;
16603
16905
  }
16604
- var _internals26 = {
16906
+ var _internals27 = {
16605
16907
  getHandoffData,
16606
16908
  formatHandoffMarkdown,
16607
16909
  formatContinuationPrompt,
@@ -16615,7 +16917,7 @@ var _internals26 = {
16615
16917
  };
16616
16918
 
16617
16919
  // src/session/snapshot-writer.ts
16618
- import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync14, openSync as openSync6, renameSync as renameSync7 } from "fs";
16920
+ import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync14, openSync as openSync6, renameSync as renameSync8 } from "fs";
16619
16921
  import * as path36 from "path";
16620
16922
  var _writeInFlight = Promise.resolve();
16621
16923
  function serializeAgentSession(s) {
@@ -16735,7 +17037,7 @@ async function writeSnapshot(directory, state) {
16735
17037
  closeSync6(fd);
16736
17038
  }
16737
17039
  } catch {}
16738
- renameSync7(tempPath, resolvedPath);
17040
+ renameSync8(tempPath, resolvedPath);
16739
17041
  } catch (error2) {
16740
17042
  log("[snapshot-writer] write failed", {
16741
17043
  error: error2 instanceof Error ? error2.message : String(error2)
@@ -16744,15 +17046,15 @@ async function writeSnapshot(directory, state) {
16744
17046
  }
16745
17047
  function createSnapshotWriterHook(directory) {
16746
17048
  return (_input, _output) => {
16747
- _writeInFlight = _writeInFlight.then(() => _internals27.writeSnapshot(directory, swarmState), () => _internals27.writeSnapshot(directory, swarmState));
17049
+ _writeInFlight = _writeInFlight.then(() => _internals28.writeSnapshot(directory, swarmState), () => _internals28.writeSnapshot(directory, swarmState));
16748
17050
  return _writeInFlight;
16749
17051
  };
16750
17052
  }
16751
17053
  async function flushPendingSnapshot(directory) {
16752
- _writeInFlight = _writeInFlight.then(() => _internals27.writeSnapshot(directory, swarmState), () => _internals27.writeSnapshot(directory, swarmState));
17054
+ _writeInFlight = _writeInFlight.then(() => _internals28.writeSnapshot(directory, swarmState), () => _internals28.writeSnapshot(directory, swarmState));
16753
17055
  await _writeInFlight;
16754
17056
  }
16755
- var _internals27 = {
17057
+ var _internals28 = {
16756
17058
  writeSnapshot,
16757
17059
  createSnapshotWriterHook,
16758
17060
  flushPendingSnapshot
@@ -16767,10 +17069,10 @@ async function handleHandoffCommand(directory, _args) {
16767
17069
  const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
16768
17070
  await bunWrite(tempPath, markdown);
16769
17071
  try {
16770
- renameSync8(tempPath, resolvedPath);
17072
+ renameSync9(tempPath, resolvedPath);
16771
17073
  } catch (renameErr) {
16772
17074
  try {
16773
- unlinkSync4(tempPath);
17075
+ unlinkSync5(tempPath);
16774
17076
  } catch {}
16775
17077
  throw renameErr;
16776
17078
  }
@@ -16779,10 +17081,10 @@ async function handleHandoffCommand(directory, _args) {
16779
17081
  const promptTempPath = `${promptPath}.tmp.${crypto4.randomUUID()}`;
16780
17082
  await bunWrite(promptTempPath, continuationPrompt);
16781
17083
  try {
16782
- renameSync8(promptTempPath, promptPath);
17084
+ renameSync9(promptTempPath, promptPath);
16783
17085
  } catch (renameErr) {
16784
17086
  try {
16785
- unlinkSync4(promptTempPath);
17087
+ unlinkSync5(promptTempPath);
16786
17088
  } catch {}
16787
17089
  throw renameErr;
16788
17090
  }
@@ -16942,7 +17244,7 @@ async function handleHistoryCommand(directory, _args) {
16942
17244
  return formatHistoryMarkdown(historyData);
16943
17245
  }
16944
17246
  // src/commands/_shared/url-security.ts
16945
- import { spawnSync as spawnSync5 } from "child_process";
17247
+ import { spawnSync as spawnSync6 } from "child_process";
16946
17248
  var MAX_URL_LEN = 2048;
16947
17249
  var IPV4_PRIVATE = /^10\./;
16948
17250
  var IPV4_LOOPBACK = /^127\./;
@@ -16952,7 +17254,7 @@ var IPV4_PRIVATE_192 = /^192\.168\./;
16952
17254
  var IPV4_ZERO_NETWORK = /^0\./;
16953
17255
  var IPV6_LINK_LOCAL = /^fe80:/i;
16954
17256
  var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
16955
- var _internals28 = { spawnSync: spawnSync5 };
17257
+ var _internals29 = { spawnSync: spawnSync6 };
16956
17258
  function sanitizeUrl(raw) {
16957
17259
  let urlStr = raw.trim();
16958
17260
  urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
@@ -17062,7 +17364,7 @@ function validateAndSanitizeGithubUrl(rawUrl, resource) {
17062
17364
  }
17063
17365
  function detectGitRemote(cwd) {
17064
17366
  try {
17065
- const result = _internals28.spawnSync("git", ["remote", "get-url", "origin"], {
17367
+ const result = _internals29.spawnSync("git", ["remote", "get-url", "origin"], {
17066
17368
  encoding: "utf-8",
17067
17369
  stdio: ["ignore", "pipe", "pipe"],
17068
17370
  timeout: 5000,
@@ -17231,7 +17533,7 @@ import { join as join30 } from "path";
17231
17533
  // src/hooks/knowledge-migrator.ts
17232
17534
  init_logger();
17233
17535
  import { randomUUID as randomUUID4 } from "crypto";
17234
- import { existsSync as existsSync21, readFileSync as readFileSync14 } from "fs";
17536
+ import { existsSync as existsSync22, readFileSync as readFileSync14 } from "fs";
17235
17537
  import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
17236
17538
  import * as os8 from "os";
17237
17539
  import * as path37 from "path";
@@ -17249,7 +17551,7 @@ async function migrateKnowledgeToExternal(_directory, _config) {
17249
17551
  skippedReason: "no-context-file"
17250
17552
  };
17251
17553
  }
17252
- var _internals29 = {
17554
+ var _internals30 = {
17253
17555
  appendKnowledge,
17254
17556
  migrateContextToKnowledge,
17255
17557
  migrateKnowledgeToExternal,
@@ -17267,7 +17569,7 @@ async function migrateContextToKnowledge(directory, config) {
17267
17569
  const sentinelPath = path37.join(directory, ".swarm", ".knowledge-migrated");
17268
17570
  const contextPath = path37.join(directory, ".swarm", "context.md");
17269
17571
  const knowledgePath = resolveSwarmKnowledgePath(directory);
17270
- if (existsSync21(sentinelPath)) {
17572
+ if (existsSync22(sentinelPath)) {
17271
17573
  return {
17272
17574
  migrated: false,
17273
17575
  entriesMigrated: 0,
@@ -17276,7 +17578,7 @@ async function migrateContextToKnowledge(directory, config) {
17276
17578
  skippedReason: "sentinel-exists"
17277
17579
  };
17278
17580
  }
17279
- if (!existsSync21(contextPath)) {
17581
+ if (!existsSync22(contextPath)) {
17280
17582
  return {
17281
17583
  migrated: false,
17282
17584
  entriesMigrated: 0,
@@ -17295,9 +17597,9 @@ async function migrateContextToKnowledge(directory, config) {
17295
17597
  skippedReason: "empty-context"
17296
17598
  };
17297
17599
  }
17298
- const rawEntries = _internals29.parseContextMd(contextContent);
17600
+ const rawEntries = _internals30.parseContextMd(contextContent);
17299
17601
  if (rawEntries.length === 0) {
17300
- await _internals29.writeSentinel(sentinelPath, 0, 0);
17602
+ await _internals30.writeSentinel(sentinelPath, 0, 0);
17301
17603
  return {
17302
17604
  migrated: true,
17303
17605
  entriesMigrated: 0,
@@ -17308,10 +17610,10 @@ async function migrateContextToKnowledge(directory, config) {
17308
17610
  const existing = await readKnowledge(knowledgePath);
17309
17611
  let migrated = 0;
17310
17612
  let dropped = 0;
17311
- const projectName = _internals29.inferProjectName(directory);
17613
+ const projectName = _internals30.inferProjectName(directory);
17312
17614
  for (const raw of rawEntries) {
17313
17615
  if (config.validation_enabled !== false) {
17314
- const category = raw.categoryHint ?? _internals29.inferCategoryFromText(raw.text);
17616
+ const category = raw.categoryHint ?? _internals30.inferCategoryFromText(raw.text);
17315
17617
  const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
17316
17618
  category,
17317
17619
  scope: "global",
@@ -17331,8 +17633,8 @@ async function migrateContextToKnowledge(directory, config) {
17331
17633
  const entry = {
17332
17634
  id: randomUUID4(),
17333
17635
  tier: "swarm",
17334
- lesson: _internals29.truncateLesson(raw.text),
17335
- category: raw.categoryHint ?? _internals29.inferCategoryFromText(raw.text),
17636
+ lesson: _internals30.truncateLesson(raw.text),
17637
+ category: raw.categoryHint ?? _internals30.inferCategoryFromText(raw.text),
17336
17638
  tags: [...inferredTags, `migration:${raw.sourceSection}`],
17337
17639
  scope: "global",
17338
17640
  confidence: 0.3,
@@ -17355,7 +17657,7 @@ async function migrateContextToKnowledge(directory, config) {
17355
17657
  if (migrated > 0) {
17356
17658
  await rewriteKnowledge(knowledgePath, existing);
17357
17659
  }
17358
- await _internals29.writeSentinel(sentinelPath, migrated, dropped);
17660
+ await _internals30.writeSentinel(sentinelPath, migrated, dropped);
17359
17661
  log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
17360
17662
  return {
17361
17663
  migrated: true,
@@ -17365,10 +17667,10 @@ async function migrateContextToKnowledge(directory, config) {
17365
17667
  };
17366
17668
  }
17367
17669
  async function migrateHiveKnowledgeLegacy(config) {
17368
- const legacyHivePath = _internals29.resolveLegacyHiveKnowledgePath();
17670
+ const legacyHivePath = _internals30.resolveLegacyHiveKnowledgePath();
17369
17671
  const canonicalHivePath = resolveHiveKnowledgePath();
17370
17672
  const sentinelPath = path37.join(path37.dirname(canonicalHivePath), ".hive-knowledge-migrated");
17371
- if (existsSync21(sentinelPath)) {
17673
+ if (existsSync22(sentinelPath)) {
17372
17674
  return {
17373
17675
  migrated: false,
17374
17676
  entriesMigrated: 0,
@@ -17377,7 +17679,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17377
17679
  skippedReason: "sentinel-exists"
17378
17680
  };
17379
17681
  }
17380
- if (!existsSync21(legacyHivePath)) {
17682
+ if (!existsSync22(legacyHivePath)) {
17381
17683
  return {
17382
17684
  migrated: false,
17383
17685
  entriesMigrated: 0,
@@ -17388,7 +17690,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17388
17690
  }
17389
17691
  const legacyEntries = await readKnowledge(legacyHivePath);
17390
17692
  if (legacyEntries.length === 0) {
17391
- await _internals29.writeSentinel(sentinelPath, 0, 0);
17693
+ await _internals30.writeSentinel(sentinelPath, 0, 0);
17392
17694
  return {
17393
17695
  migrated: true,
17394
17696
  entriesMigrated: 0,
@@ -17436,7 +17738,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17436
17738
  const newHiveEntry = {
17437
17739
  id: resolvedId,
17438
17740
  tier: "hive",
17439
- lesson: _internals29.truncateLesson(lesson),
17741
+ lesson: _internals30.truncateLesson(lesson),
17440
17742
  category,
17441
17743
  tags: ["migration:legacy-hive"],
17442
17744
  scope: scopeTag,
@@ -17455,7 +17757,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17455
17757
  encounter_score: 1
17456
17758
  };
17457
17759
  try {
17458
- await _internals29.appendKnowledge(canonicalHivePath, newHiveEntry);
17760
+ await _internals30.appendKnowledge(canonicalHivePath, newHiveEntry);
17459
17761
  existingHiveEntries.push(newHiveEntry);
17460
17762
  migrated++;
17461
17763
  } catch (appendError) {
@@ -17471,7 +17773,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17471
17773
  dropped++;
17472
17774
  }
17473
17775
  }
17474
- await _internals29.writeSentinel(sentinelPath, migrated, dropped);
17776
+ await _internals30.writeSentinel(sentinelPath, migrated, dropped);
17475
17777
  log(`[knowledge-migrator] Migrated ${migrated} legacy hive entries, dropped ${dropped}`);
17476
17778
  return {
17477
17779
  migrated: true,
@@ -17482,7 +17784,7 @@ async function migrateHiveKnowledgeLegacy(config) {
17482
17784
  };
17483
17785
  }
17484
17786
  function parseContextMd(content) {
17485
- const sections = _internals29.splitIntoSections(content);
17787
+ const sections = _internals30.splitIntoSections(content);
17486
17788
  const entries = [];
17487
17789
  const seen = new Set;
17488
17790
  const sectionPatterns = [
@@ -17498,7 +17800,7 @@ function parseContextMd(content) {
17498
17800
  const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
17499
17801
  if (!match)
17500
17802
  continue;
17501
- const bullets = _internals29.extractBullets(section.body);
17803
+ const bullets = _internals30.extractBullets(section.body);
17502
17804
  for (const bullet of bullets) {
17503
17805
  if (bullet.length < 15)
17504
17806
  continue;
@@ -17507,9 +17809,9 @@ function parseContextMd(content) {
17507
17809
  continue;
17508
17810
  seen.add(normalized);
17509
17811
  entries.push({
17510
- text: _internals29.truncateLesson(bullet),
17812
+ text: _internals30.truncateLesson(bullet),
17511
17813
  sourceSection: match.sourceSection,
17512
- categoryHint: _internals29.inferCategoryFromText(bullet)
17814
+ categoryHint: _internals30.inferCategoryFromText(bullet)
17513
17815
  });
17514
17816
  }
17515
17817
  }
@@ -17579,7 +17881,7 @@ function truncateLesson2(text) {
17579
17881
  }
17580
17882
  function inferProjectName(directory) {
17581
17883
  const packageJsonPath = path37.join(directory, "package.json");
17582
- if (existsSync21(packageJsonPath)) {
17884
+ if (existsSync22(packageJsonPath)) {
17583
17885
  try {
17584
17886
  const pkg = JSON.parse(readFileSync14(packageJsonPath, "utf-8"));
17585
17887
  if (pkg.name && typeof pkg.name === "string") {
@@ -17856,7 +18158,7 @@ function timeoutMessage(timeoutMs) {
17856
18158
  async function computeWithTimeout(directory, currentPhase, timeoutMs) {
17857
18159
  const controller = new AbortController;
17858
18160
  let timeout;
17859
- const metricsPromise = _internals30.computeLearningMetrics(directory, {
18161
+ const metricsPromise = _internals31.computeLearningMetrics(directory, {
17860
18162
  currentPhase,
17861
18163
  signal: controller.signal
17862
18164
  });
@@ -17913,7 +18215,7 @@ ${JSON.stringify({
17913
18215
  return `Error computing learning metrics: ${message}. Run /swarm diagnose to check .swarm/ health.`;
17914
18216
  }
17915
18217
  }
17916
- var _internals30 = {
18218
+ var _internals31 = {
17917
18219
  computeLearningMetrics
17918
18220
  };
17919
18221
 
@@ -18032,7 +18334,7 @@ ${USAGE7}`;
18032
18334
  }
18033
18335
 
18034
18336
  // src/commands/memory.ts
18035
- import { existsSync as existsSync24 } from "fs";
18337
+ import { existsSync as existsSync25 } from "fs";
18036
18338
  import * as path42 from "path";
18037
18339
  import { fileURLToPath as fileURLToPath2 } from "url";
18038
18340
 
@@ -18130,7 +18432,7 @@ import * as path41 from "path";
18130
18432
 
18131
18433
  // src/memory/local-jsonl-provider.ts
18132
18434
  import { randomUUID as randomUUID5 } from "crypto";
18133
- import { existsSync as existsSync22 } from "fs";
18435
+ import { existsSync as existsSync23 } from "fs";
18134
18436
  import {
18135
18437
  appendFile as appendFile3,
18136
18438
  mkdir as mkdir10,
@@ -19297,7 +19599,7 @@ function validateLoadedProposals(values, config) {
19297
19599
  return { records, invalidCount };
19298
19600
  }
19299
19601
  async function readJsonl(filePath) {
19300
- if (!existsSync22(filePath))
19602
+ if (!existsSync23(filePath))
19301
19603
  return [];
19302
19604
  const content = await readFile12(filePath, "utf-8");
19303
19605
  const records = [];
@@ -19374,7 +19676,7 @@ import { createRequire as createRequire2 } from "module";
19374
19676
  import * as path40 from "path";
19375
19677
 
19376
19678
  // src/memory/jsonl-migration.ts
19377
- import { existsSync as existsSync23 } from "fs";
19679
+ import { existsSync as existsSync24, renameSync as renameSync10, unlinkSync as unlinkSync6 } from "fs";
19378
19680
  import { copyFile as copyFile2, mkdir as mkdir11, readFile as readFile13, stat as stat5, writeFile as writeFile11 } from "fs/promises";
19379
19681
  import * as path39 from "path";
19380
19682
  var LEGACY_JSONL_MIGRATION_VERSION = 2;
@@ -19408,10 +19710,10 @@ async function backupLegacyJsonl(rootDirectory, config = {}) {
19408
19710
  const results = [];
19409
19711
  for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
19410
19712
  const source = path39.join(storageDir, filename);
19411
- if (!existsSync23(source))
19713
+ if (!existsSync24(source))
19412
19714
  continue;
19413
19715
  const backup = path39.join(backupDir, `${filename}.pre-sqlite-migration`);
19414
- if (existsSync23(backup)) {
19716
+ if (existsSync24(backup)) {
19415
19717
  results.push({ source, backup, created: false });
19416
19718
  continue;
19417
19719
  }
@@ -19425,20 +19727,47 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
19425
19727
  await mkdir11(exportDir, { recursive: true });
19426
19728
  const memoriesPath = path39.join(exportDir, "memories.jsonl");
19427
19729
  const proposalsPath = path39.join(exportDir, "proposals.jsonl");
19428
- await writeFile11(memoriesPath, toJsonl(memories), "utf-8");
19429
- await writeFile11(proposalsPath, toJsonl(proposals), "utf-8");
19730
+ const memoriesTempPath = path39.join(path39.dirname(memoriesPath), `${path39.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
19731
+ try {
19732
+ await writeFile11(memoriesTempPath, toJsonl(memories), "utf-8");
19733
+ renameSync10(memoriesTempPath, memoriesPath);
19734
+ } catch (err) {
19735
+ try {
19736
+ unlinkSync6(memoriesTempPath);
19737
+ } catch {}
19738
+ throw err;
19739
+ }
19740
+ const proposalsTempPath = path39.join(path39.dirname(proposalsPath), `${path39.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
19741
+ try {
19742
+ await writeFile11(proposalsTempPath, toJsonl(proposals), "utf-8");
19743
+ renameSync10(proposalsTempPath, proposalsPath);
19744
+ } catch (err) {
19745
+ try {
19746
+ unlinkSync6(proposalsTempPath);
19747
+ } catch {}
19748
+ throw err;
19749
+ }
19430
19750
  return { directory: exportDir, memoriesPath, proposalsPath };
19431
19751
  }
19432
19752
  async function writeMigrationReport(rootDirectory, report, config = {}) {
19433
19753
  const reportPath = path39.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
19434
19754
  await mkdir11(path39.dirname(reportPath), { recursive: true });
19435
- await writeFile11(reportPath, `${JSON.stringify(report, null, 2)}
19755
+ const reportTempPath = path39.join(path39.dirname(reportPath), `${path39.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
19756
+ try {
19757
+ await writeFile11(reportTempPath, `${JSON.stringify(report, null, 2)}
19436
19758
  `, "utf-8");
19759
+ renameSync10(reportTempPath, reportPath);
19760
+ } catch (err) {
19761
+ try {
19762
+ unlinkSync6(reportTempPath);
19763
+ } catch {}
19764
+ throw err;
19765
+ }
19437
19766
  return reportPath;
19438
19767
  }
19439
19768
  async function readMigrationReport(rootDirectory, config = {}) {
19440
19769
  const reportPath = path39.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
19441
- if (!existsSync23(reportPath))
19770
+ if (!existsSync24(reportPath))
19442
19771
  return null;
19443
19772
  try {
19444
19773
  return JSON.parse(await readFile13(reportPath, "utf-8"));
@@ -19452,13 +19781,13 @@ async function getLegacyJsonlFileStatus(rootDirectory, config = {}) {
19452
19781
  for (const file of ["memories.jsonl", "proposals.jsonl"]) {
19453
19782
  const filePath = path39.join(storageDir, file);
19454
19783
  let sizeBytes = 0;
19455
- if (existsSync23(filePath)) {
19784
+ if (existsSync24(filePath)) {
19456
19785
  sizeBytes = (await stat5(filePath)).size;
19457
19786
  }
19458
19787
  statuses.push({
19459
19788
  file,
19460
19789
  path: filePath,
19461
- exists: existsSync23(filePath),
19790
+ exists: existsSync24(filePath),
19462
19791
  sizeBytes
19463
19792
  });
19464
19793
  }
@@ -19539,7 +19868,7 @@ async function readProposalJsonl(filePath, config) {
19539
19868
  return { records, invalidRows, totalRows: rows.totalRows };
19540
19869
  }
19541
19870
  async function readJsonlRows(filePath) {
19542
- if (!existsSync23(filePath)) {
19871
+ if (!existsSync24(filePath)) {
19543
19872
  return { rows: [], invalidRows: [], totalRows: 0 };
19544
19873
  }
19545
19874
  const content = await readFile13(filePath, "utf-8");
@@ -20929,7 +21258,7 @@ async function handleMemoryStatusCommand(directory, _args) {
20929
21258
  `- Provider: \`${config.provider}\``,
20930
21259
  `- Storage: \`${storageDir}\``,
20931
21260
  `- SQLite path: \`${sqlitePath}\``,
20932
- `- SQLite database exists: \`${existsSync24(sqlitePath)}\``,
21261
+ `- SQLite database exists: \`${existsSync25(sqlitePath)}\``,
20933
21262
  `- Automatic destructive cleanup: \`disabled\``,
20934
21263
  "",
20935
21264
  "### Legacy JSONL"
@@ -21349,15 +21678,15 @@ function truncate(value, maxLength) {
21349
21678
  }
21350
21679
 
21351
21680
  // src/services/plan-service.ts
21352
- var _internals31 = {
21681
+ var _internals32 = {
21353
21682
  loadPlanJsonOnly,
21354
21683
  derivePlanMarkdown,
21355
21684
  readSwarmFileAsync
21356
21685
  };
21357
21686
  async function getPlanData(directory, phaseArg) {
21358
- const plan = await _internals31.loadPlanJsonOnly(directory);
21687
+ const plan = await _internals32.loadPlanJsonOnly(directory);
21359
21688
  if (plan) {
21360
- const fullMarkdown = _internals31.derivePlanMarkdown(plan);
21689
+ const fullMarkdown = _internals32.derivePlanMarkdown(plan);
21361
21690
  if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
21362
21691
  return {
21363
21692
  hasPlan: true,
@@ -21400,7 +21729,7 @@ async function getPlanData(directory, phaseArg) {
21400
21729
  isLegacy: false
21401
21730
  };
21402
21731
  }
21403
- const planContent = await _internals31.readSwarmFileAsync(directory, "plan.md");
21732
+ const planContent = await _internals32.readSwarmFileAsync(directory, "plan.md");
21404
21733
  if (!planContent) {
21405
21734
  return {
21406
21735
  hasPlan: false,
@@ -21497,7 +21826,7 @@ async function handlePlanCommand(directory, args) {
21497
21826
  return formatPlanMarkdown(planData);
21498
21827
  }
21499
21828
  // src/commands/post-mortem.ts
21500
- var _internals32 = {
21829
+ var _internals33 = {
21501
21830
  createCuratorLLMDelegate,
21502
21831
  runCuratorPostMortem
21503
21832
  };
@@ -21509,10 +21838,10 @@ async function handlePostMortemCommand(directory, args, options) {
21509
21838
  };
21510
21839
  if (options?.sessionID) {
21511
21840
  try {
21512
- pmOptions.llmDelegate = _internals32.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
21841
+ pmOptions.llmDelegate = _internals33.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
21513
21842
  } catch {}
21514
21843
  }
21515
- const result = await _internals32.runCuratorPostMortem(directory, pmOptions);
21844
+ const result = await _internals33.runCuratorPostMortem(directory, pmOptions);
21516
21845
  const lines = [];
21517
21846
  if (result.success) {
21518
21847
  lines.push("## Post-Mortem Report Generated");
@@ -21667,12 +21996,12 @@ function formatRelativeTime(epochMs) {
21667
21996
  const diffDays = Math.floor(diffHours / 24);
21668
21997
  return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
21669
21998
  }
21670
- var _internals33 = {
21999
+ var _internals34 = {
21671
22000
  formatRelativeTime,
21672
22001
  listActive
21673
22002
  };
21674
22003
  async function handlePrMonitorStatusCommand(directory, _args, sessionID) {
21675
- const allActive = await _internals33.listActive(directory);
22004
+ const allActive = await _internals34.listActive(directory);
21676
22005
  const sessionSubs = allActive.filter((record) => record.sessionID === sessionID);
21677
22006
  if (sessionSubs.length === 0) {
21678
22007
  return "No active PR subscriptions for this session.";
@@ -21797,7 +22126,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
21797
22126
  const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
21798
22127
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
21799
22128
  try {
21800
- const config = _internals34.loadPluginConfig(directory);
22129
+ const config = _internals35.loadPluginConfig(directory);
21801
22130
  const prMonitorConfig = config.pr_monitor;
21802
22131
  if (!prMonitorConfig?.enabled) {
21803
22132
  return [
@@ -21807,7 +22136,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
21807
22136
  ].join(`
21808
22137
  `);
21809
22138
  }
21810
- await _internals34.subscribe(directory, {
22139
+ await _internals35.subscribe(directory, {
21811
22140
  sessionID,
21812
22141
  prNumber: prInfo.number,
21813
22142
  repoFullName,
@@ -21831,7 +22160,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
21831
22160
  `);
21832
22161
  }
21833
22162
  }
21834
- var _internals34 = {
22163
+ var _internals35 = {
21835
22164
  loadPluginConfig,
21836
22165
  subscribe
21837
22166
  };
@@ -21854,9 +22183,9 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
21854
22183
  `);
21855
22184
  }
21856
22185
  const refToken = rest[0];
21857
- const prInfo = _internals35.parsePrRef(refToken, directory);
22186
+ const prInfo = _internals36.parsePrRef(refToken, directory);
21858
22187
  if (!prInfo) {
21859
- if (_internals35.looksLikePrRef(refToken)) {
22188
+ if (_internals36.looksLikePrRef(refToken)) {
21860
22189
  return [
21861
22190
  `Error: Could not resolve PR reference from "${refToken}".`,
21862
22191
  "",
@@ -21877,8 +22206,8 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
21877
22206
  const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
21878
22207
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
21879
22208
  try {
21880
- const correlationId = _internals35.buildCorrelationId(sessionID, repoFullName, prInfo.number);
21881
- const result = await _internals35.unsubscribe(directory, correlationId);
22209
+ const correlationId = _internals36.buildCorrelationId(sessionID, repoFullName, prInfo.number);
22210
+ const result = await _internals36.unsubscribe(directory, correlationId);
21882
22211
  if (!result) {
21883
22212
  return [
21884
22213
  `Not subscribed to ${prUrl}`,
@@ -21905,7 +22234,7 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
21905
22234
  `);
21906
22235
  }
21907
22236
  }
21908
- var _internals35 = {
22237
+ var _internals36 = {
21909
22238
  unsubscribe,
21910
22239
  buildCorrelationId,
21911
22240
  parsePrRef,
@@ -22339,15 +22668,15 @@ var lint = createSwarmTool({
22339
22668
  }
22340
22669
  const { mode } = args;
22341
22670
  const cwd = directory;
22342
- const linter = await _internals36.detectAvailableLinter(directory);
22671
+ const linter = await _internals37.detectAvailableLinter(directory);
22343
22672
  if (linter) {
22344
- const result = await _internals36.runLint(linter, mode, directory);
22673
+ const result = await _internals37.runLint(linter, mode, directory);
22345
22674
  return JSON.stringify(result, null, 2);
22346
22675
  }
22347
- const additionalLinter = _internals36.detectAdditionalLinter(cwd);
22676
+ const additionalLinter = _internals37.detectAdditionalLinter(cwd);
22348
22677
  if (additionalLinter) {
22349
22678
  warn(`[lint] Using ${additionalLinter} linter for this project`);
22350
- const result = await _internals36.runAdditionalLint(additionalLinter, mode, cwd);
22679
+ const result = await _internals37.runAdditionalLint(additionalLinter, mode, cwd);
22351
22680
  return JSON.stringify(result, null, 2);
22352
22681
  }
22353
22682
  const errorResult = {
@@ -22361,7 +22690,7 @@ For Rust: rustup component add clippy`
22361
22690
  return JSON.stringify(errorResult, null, 2);
22362
22691
  }
22363
22692
  });
22364
- var _internals36 = {
22693
+ var _internals37 = {
22365
22694
  detectAvailableLinter,
22366
22695
  runLint,
22367
22696
  detectAdditionalLinter,
@@ -23049,7 +23378,7 @@ var secretscan = createSwarmTool({
23049
23378
  });
23050
23379
  async function runSecretscan(directory) {
23051
23380
  try {
23052
- const result = await _internals37.secretscan.execute({ directory }, {});
23381
+ const result = await _internals38.secretscan.execute({ directory }, {});
23053
23382
  const jsonStr = typeof result === "string" ? result : result.output;
23054
23383
  return JSON.parse(jsonStr);
23055
23384
  } catch (e) {
@@ -23064,7 +23393,7 @@ async function runSecretscan(directory) {
23064
23393
  return errorResult;
23065
23394
  }
23066
23395
  }
23067
- var _internals37 = {
23396
+ var _internals38 = {
23068
23397
  secretscan,
23069
23398
  runSecretscan
23070
23399
  };
@@ -23337,7 +23666,7 @@ async function buildImpactMapInternal(cwd) {
23337
23666
  }
23338
23667
  return impactMap;
23339
23668
  }
23340
- var _internals38 = {
23669
+ var _internals39 = {
23341
23670
  validateProjectRoot,
23342
23671
  normalizePath: normalizePath2,
23343
23672
  isCacheStale,
@@ -23352,8 +23681,8 @@ var _internals38 = {
23352
23681
  _clearGoModuleCache
23353
23682
  };
23354
23683
  async function buildImpactMap(cwd) {
23355
- const impactMap = await _internals38.buildImpactMapInternal(cwd);
23356
- await _internals38.saveImpactMap(cwd, impactMap);
23684
+ const impactMap = await _internals39.buildImpactMapInternal(cwd);
23685
+ await _internals39.saveImpactMap(cwd, impactMap);
23357
23686
  return impactMap;
23358
23687
  }
23359
23688
  async function loadImpactMap(cwd, options) {
@@ -23367,7 +23696,7 @@ async function loadImpactMap(cwd, options) {
23367
23696
  const hasValidValues = Object.values(map).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
23368
23697
  if (hasValidValues) {
23369
23698
  const generatedAt = new Date(data.generatedAt).getTime();
23370
- if (!_internals38.isCacheStale(map, generatedAt)) {
23699
+ if (!_internals39.isCacheStale(map, generatedAt)) {
23371
23700
  return map;
23372
23701
  }
23373
23702
  if (options?.skipRebuild) {
@@ -23387,13 +23716,13 @@ async function loadImpactMap(cwd, options) {
23387
23716
  if (options?.skipRebuild) {
23388
23717
  return {};
23389
23718
  }
23390
- return _internals38.buildImpactMap(cwd);
23719
+ return _internals39.buildImpactMap(cwd);
23391
23720
  }
23392
23721
  async function saveImpactMap(cwd, impactMap) {
23393
23722
  if (!path45.isAbsolute(cwd)) {
23394
23723
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
23395
23724
  }
23396
- _internals38.validateProjectRoot(cwd);
23725
+ _internals39.validateProjectRoot(cwd);
23397
23726
  const cacheDir2 = path45.join(cwd, ".swarm", "cache");
23398
23727
  const cachePath = path45.join(cacheDir2, "impact-map.json");
23399
23728
  if (!fs20.existsSync(cacheDir2)) {
@@ -23417,7 +23746,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
23417
23746
  };
23418
23747
  }
23419
23748
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
23420
- const impactMap = await _internals38.loadImpactMap(cwd);
23749
+ const impactMap = await _internals39.loadImpactMap(cwd);
23421
23750
  const impactedTestsSet = new Set;
23422
23751
  const untestedFiles = [];
23423
23752
  let visitedCount = 0;
@@ -23882,7 +24211,7 @@ function batchAppendTestRuns(records, workingDir) {
23882
24211
  }
23883
24212
  const historyPath = getHistoryPath(workingDir);
23884
24213
  const historyDir = path46.dirname(historyPath);
23885
- _internals39.validateProjectRoot(workingDir);
24214
+ _internals40.validateProjectRoot(workingDir);
23886
24215
  if (!fs21.existsSync(historyDir)) {
23887
24216
  fs21.mkdirSync(historyDir, { recursive: true });
23888
24217
  }
@@ -24005,7 +24334,7 @@ function getAllHistory(workingDir) {
24005
24334
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
24006
24335
  return records;
24007
24336
  }
24008
- var _internals39 = {
24337
+ var _internals40 = {
24009
24338
  validateProjectRoot
24010
24339
  };
24011
24340
 
@@ -24477,19 +24806,19 @@ function hasCompoundTestExtension(filename) {
24477
24806
  const lower = filename.toLowerCase();
24478
24807
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
24479
24808
  }
24480
- function isLanguageSpecificTestFile(basename8) {
24481
- const lower = basename8.toLowerCase();
24809
+ function isLanguageSpecificTestFile(basename9) {
24810
+ const lower = basename9.toLowerCase();
24482
24811
  if (lower.endsWith("_test.go"))
24483
24812
  return true;
24484
24813
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
24485
24814
  return true;
24486
24815
  if (lower.endsWith("_spec.rb"))
24487
24816
  return true;
24488
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename8) || basename8.endsWith("Test.java") || basename8.endsWith("Tests.java") || lower.endsWith("it.java")))
24817
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename9) || basename9.endsWith("Test.java") || basename9.endsWith("Tests.java") || lower.endsWith("it.java")))
24489
24818
  return true;
24490
24819
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
24491
24820
  return true;
24492
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename8) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
24821
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename9) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
24493
24822
  return true;
24494
24823
  if (lower.endsWith(".tests.ps1"))
24495
24824
  return true;
@@ -24497,23 +24826,23 @@ function isLanguageSpecificTestFile(basename8) {
24497
24826
  }
24498
24827
  function isConventionTestFilePath(filePath) {
24499
24828
  const normalizedPath = filePath.replace(/\\/g, "/");
24500
- const basename8 = path48.basename(filePath);
24501
- return hasCompoundTestExtension(basename8) || basename8.includes(".spec.") || basename8.includes(".test.") || isLanguageSpecificTestFile(basename8) || isTestDirectoryPath(normalizedPath);
24829
+ const basename9 = path48.basename(filePath);
24830
+ return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
24502
24831
  }
24503
24832
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24504
24833
  const testFiles = [];
24505
24834
  for (const file of sourceFiles) {
24506
24835
  const absoluteFile = resolveWorkspacePath(file, workingDir);
24507
24836
  const relativeFile = path48.relative(workingDir, absoluteFile);
24508
- const basename8 = path48.basename(absoluteFile);
24837
+ const basename9 = path48.basename(absoluteFile);
24509
24838
  const dirname23 = path48.dirname(absoluteFile);
24510
24839
  const preferRelativeOutput = !path48.isAbsolute(file);
24511
24840
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
24512
24841
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
24513
24842
  continue;
24514
24843
  }
24515
- const nameWithoutExt = basename8.replace(/\.[^.]+$/, "");
24516
- const ext = path48.extname(basename8);
24844
+ const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
24845
+ const ext = path48.extname(basename9);
24517
24846
  const genericTestNames = [
24518
24847
  `${nameWithoutExt}.spec${ext}`,
24519
24848
  `${nameWithoutExt}.test${ext}`
@@ -24524,7 +24853,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24524
24853
  ...languageSpecificTestNames
24525
24854
  ].map((candidateName) => path48.join(dirname23, candidateName));
24526
24855
  const testDirectoryNames = [
24527
- basename8,
24856
+ basename9,
24528
24857
  ...genericTestNames,
24529
24858
  ...languageSpecificTestNames
24530
24859
  ];
@@ -25918,9 +26247,9 @@ function getVersionFileVersion(dir) {
25918
26247
  async function runVersionCheck(dir, _timeoutMs) {
25919
26248
  const startTime = Date.now();
25920
26249
  try {
25921
- const packageVersion = _internals40.getPackageVersion(dir);
25922
- const changelogVersion = _internals40.getChangelogVersion(dir);
25923
- const versionFileVersion = _internals40.getVersionFileVersion(dir);
26250
+ const packageVersion = _internals41.getPackageVersion(dir);
26251
+ const changelogVersion = _internals41.getChangelogVersion(dir);
26252
+ const versionFileVersion = _internals41.getVersionFileVersion(dir);
25924
26253
  const versions = [];
25925
26254
  if (packageVersion)
25926
26255
  versions.push(`package.json: ${packageVersion}`);
@@ -26284,7 +26613,7 @@ async function runPreflight(dir, phase, config) {
26284
26613
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
26285
26614
  let validatedDir;
26286
26615
  try {
26287
- validatedDir = _internals40.validateDirectoryPath(dir);
26616
+ validatedDir = _internals41.validateDirectoryPath(dir);
26288
26617
  } catch (error2) {
26289
26618
  return {
26290
26619
  id: reportId,
@@ -26304,7 +26633,7 @@ async function runPreflight(dir, phase, config) {
26304
26633
  }
26305
26634
  let validatedTimeout;
26306
26635
  try {
26307
- validatedTimeout = _internals40.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
26636
+ validatedTimeout = _internals41.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
26308
26637
  } catch (error2) {
26309
26638
  return {
26310
26639
  id: reportId,
@@ -26345,12 +26674,12 @@ async function runPreflight(dir, phase, config) {
26345
26674
  });
26346
26675
  const checks = [];
26347
26676
  log("[Preflight] Running lint check...");
26348
- const lintResult = await _internals40.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
26677
+ const lintResult = await _internals41.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
26349
26678
  checks.push(lintResult);
26350
26679
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
26351
26680
  if (!cfg.skipTests) {
26352
26681
  log("[Preflight] Running tests check...");
26353
- const testsResult = await _internals40.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
26682
+ const testsResult = await _internals41.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
26354
26683
  checks.push(testsResult);
26355
26684
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
26356
26685
  } else {
@@ -26362,7 +26691,7 @@ async function runPreflight(dir, phase, config) {
26362
26691
  }
26363
26692
  if (!cfg.skipSecrets) {
26364
26693
  log("[Preflight] Running secrets check...");
26365
- const secretsResult = await _internals40.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
26694
+ const secretsResult = await _internals41.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
26366
26695
  checks.push(secretsResult);
26367
26696
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
26368
26697
  } else {
@@ -26374,7 +26703,7 @@ async function runPreflight(dir, phase, config) {
26374
26703
  }
26375
26704
  if (!cfg.skipEvidence) {
26376
26705
  log("[Preflight] Running evidence check...");
26377
- const evidenceResult = await _internals40.runEvidenceCheck(validatedDir);
26706
+ const evidenceResult = await _internals41.runEvidenceCheck(validatedDir);
26378
26707
  checks.push(evidenceResult);
26379
26708
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
26380
26709
  } else {
@@ -26385,12 +26714,12 @@ async function runPreflight(dir, phase, config) {
26385
26714
  });
26386
26715
  }
26387
26716
  log("[Preflight] Running requirement coverage check...");
26388
- const reqCoverageResult = await _internals40.runRequirementCoverageCheck(validatedDir, phase);
26717
+ const reqCoverageResult = await _internals41.runRequirementCoverageCheck(validatedDir, phase);
26389
26718
  checks.push(reqCoverageResult);
26390
26719
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
26391
26720
  if (!cfg.skipVersion) {
26392
26721
  log("[Preflight] Running version check...");
26393
- const versionResult = await _internals40.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
26722
+ const versionResult = await _internals41.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
26394
26723
  checks.push(versionResult);
26395
26724
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
26396
26725
  } else {
@@ -26453,10 +26782,10 @@ function formatPreflightMarkdown(report) {
26453
26782
  async function handlePreflightCommand(directory, _args) {
26454
26783
  const plan = await loadPlan(directory);
26455
26784
  const phase = plan?.current_phase ?? 1;
26456
- const report = await _internals40.runPreflight(directory, phase);
26457
- return _internals40.formatPreflightMarkdown(report);
26785
+ const report = await _internals41.runPreflight(directory, phase);
26786
+ return _internals41.formatPreflightMarkdown(report);
26458
26787
  }
26459
- var _internals40 = {
26788
+ var _internals41 = {
26460
26789
  runPreflight,
26461
26790
  formatPreflightMarkdown,
26462
26791
  handlePreflightCommand,
@@ -27362,7 +27691,9 @@ async function handleResetCommand(directory, args) {
27362
27691
  fs25.unlinkSync(rootPath);
27363
27692
  results.push(`- \u2705 Deleted ${filename} (root)`);
27364
27693
  }
27365
- } catch {}
27694
+ } catch (err) {
27695
+ results.push(`- \u274C Failed to delete ${filename}: ${err instanceof Error ? err.message : String(err)}`);
27696
+ }
27366
27697
  }
27367
27698
  try {
27368
27699
  resetAutomationManager();
@@ -27857,7 +28188,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
27857
28188
  }
27858
28189
 
27859
28190
  // src/prm/index.ts
27860
- var _internals41 = {
28191
+ var _internals42 = {
27861
28192
  getAgentSession,
27862
28193
  readTrajectory,
27863
28194
  getInMemoryTrajectory,
@@ -27880,11 +28211,16 @@ function resetPrmSessionState(session, sessionId) {
27880
28211
  session.prmTrajectoryStep = 0;
27881
28212
  session.replayArtifactPath = null;
27882
28213
  if (sessionId) {
27883
- _internals41.clearTrajectoryCache(sessionId);
28214
+ _internals42.clearTrajectoryCache(sessionId);
27884
28215
  }
27885
28216
  }
27886
28217
 
27887
28218
  // src/commands/reset-session.ts
28219
+ function errorMessage(err) {
28220
+ if (err instanceof Error)
28221
+ return err.message;
28222
+ return String(err);
28223
+ }
27888
28224
  async function handleResetSessionCommand(directory, _args) {
27889
28225
  const results = [];
27890
28226
  try {
@@ -27898,22 +28234,30 @@ async function handleResetSessionCommand(directory, _args) {
27898
28234
  } catch {
27899
28235
  results.push("\u274C Failed to delete state.json");
27900
28236
  }
27901
- try {
27902
- const sessionDir = path52.dirname(validateSwarmPath(directory, "session/state.json"));
27903
- if (fs27.existsSync(sessionDir)) {
27904
- const files = fs27.readdirSync(sessionDir);
27905
- const otherFiles = files.filter((f) => f !== "state.json");
27906
- let deletedCount = 0;
27907
- for (const file of otherFiles) {
27908
- const filePath = path52.join(sessionDir, file);
27909
- if (fs27.lstatSync(filePath).isFile()) {
27910
- fs27.unlinkSync(filePath);
27911
- deletedCount++;
27912
- }
27913
- }
27914
- results.push(`\u2705 Cleaned ${deletedCount} additional session file(s)`);
28237
+ const sessionDir = path52.dirname(validateSwarmPath(directory, "session/state.json"));
28238
+ let sessionFiles = [];
28239
+ if (fs27.existsSync(sessionDir)) {
28240
+ try {
28241
+ sessionFiles = fs27.readdirSync(sessionDir);
28242
+ } catch (err) {
28243
+ results.push(`\u274C Failed to read session directory: ${errorMessage(err)}`);
27915
28244
  }
27916
- } catch {}
28245
+ }
28246
+ for (const file of sessionFiles) {
28247
+ if (file === "state.json")
28248
+ continue;
28249
+ const filePath = path52.join(sessionDir, file);
28250
+ try {
28251
+ if (!fs27.existsSync(filePath))
28252
+ continue;
28253
+ if (!fs27.lstatSync(filePath).isFile())
28254
+ continue;
28255
+ fs27.unlinkSync(filePath);
28256
+ results.push(`\u2713 Deleted ${file}`);
28257
+ } catch (err) {
28258
+ results.push(`\u274C Failed to delete ${file}: ${errorMessage(err)}`);
28259
+ }
28260
+ }
27917
28261
  const sessionCount = swarmState.agentSessions.size;
27918
28262
  for (const [sessionId, session] of swarmState.agentSessions) {
27919
28263
  resetPrmSessionState(session, sessionId);
@@ -28075,6 +28419,7 @@ async function handleRollbackCommand(directory, args) {
28075
28419
  ]);
28076
28420
  const successes = [];
28077
28421
  const failures = [];
28422
+ const warnings = [];
28078
28423
  for (const file of checkpointFiles) {
28079
28424
  if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
28080
28425
  continue;
@@ -28100,30 +28445,39 @@ async function handleRollbackCommand(directory, args) {
28100
28445
  `);
28101
28446
  }
28102
28447
  const existingLedgerPath = path54.join(swarmDir, "plan-ledger.jsonl");
28448
+ let ledgerDeletionFailed = false;
28103
28449
  if (fs28.existsSync(existingLedgerPath)) {
28104
- fs28.unlinkSync(existingLedgerPath);
28105
- }
28106
- try {
28107
- const planJsonPath = path54.join(swarmDir, "plan.json");
28108
- if (fs28.existsSync(planJsonPath)) {
28109
- const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
28110
- const plan = PlanSchema.parse(JSON.parse(planRaw));
28111
- const planId = derivePlanId(plan);
28112
- const planHash = computePlanHash(plan);
28113
- await initLedger(directory, planId, planHash, plan);
28114
- await appendLedgerEvent(directory, {
28115
- event_type: "plan_rebuilt",
28116
- source: "rollback",
28117
- plan_id: planId
28118
- });
28450
+ try {
28451
+ fs28.unlinkSync(existingLedgerPath);
28452
+ } catch (err) {
28453
+ ledgerDeletionFailed = true;
28454
+ const errMsg = err instanceof Error ? err.message : String(err);
28455
+ warnings.push(`\u26A0\uFE0F 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.`);
28119
28456
  }
28120
- } catch (initError) {
28121
- return [
28122
- `Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
28123
- "The .swarm/plan.json has been restored but the ledger may be out of sync.",
28124
- "Run /swarm reset-session to reinitialize the ledger."
28125
- ].join(`
28457
+ }
28458
+ if (!ledgerDeletionFailed) {
28459
+ try {
28460
+ const planJsonPath = path54.join(swarmDir, "plan.json");
28461
+ if (fs28.existsSync(planJsonPath)) {
28462
+ const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
28463
+ const plan = PlanSchema.parse(JSON.parse(planRaw));
28464
+ const planId = derivePlanId(plan);
28465
+ const planHash = computePlanHash(plan);
28466
+ await initLedger(directory, planId, planHash, plan);
28467
+ await appendLedgerEvent(directory, {
28468
+ event_type: "plan_rebuilt",
28469
+ source: "rollback",
28470
+ plan_id: planId
28471
+ });
28472
+ }
28473
+ } catch (initError) {
28474
+ return [
28475
+ `Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
28476
+ "The .swarm/plan.json has been restored but the ledger may be out of sync.",
28477
+ "Run /swarm reset-session to reinitialize the ledger."
28478
+ ].join(`
28126
28479
  `);
28480
+ }
28127
28481
  }
28128
28482
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
28129
28483
  const rollbackEvent = {
@@ -28138,6 +28492,14 @@ async function handleRollbackCommand(directory, args) {
28138
28492
  } catch (error2) {
28139
28493
  console.error("Failed to write rollback event:", error2 instanceof Error ? error2.message : String(error2));
28140
28494
  }
28495
+ if (warnings.length > 0) {
28496
+ return [
28497
+ ...warnings,
28498
+ "",
28499
+ `Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`
28500
+ ].join(`
28501
+ `);
28502
+ }
28141
28503
  return `Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`;
28142
28504
  }
28143
28505
 
@@ -28307,6 +28669,7 @@ async function handleSddCommand(_directory, _args) {
28307
28669
  }
28308
28670
 
28309
28671
  // src/commands/simulate.ts
28672
+ import { renameSync as renameSync11, unlinkSync as unlinkSync11 } from "fs";
28310
28673
  async function handleSimulateCommand(directory, args) {
28311
28674
  const thresholdIndex = args.indexOf("--threshold");
28312
28675
  const minCommitsIndex = args.indexOf("--min-commits");
@@ -28325,7 +28688,7 @@ async function handleSimulateCommand(directory, args) {
28325
28688
  }
28326
28689
  let darkMatterPairs;
28327
28690
  try {
28328
- darkMatterPairs = await _internals20.detectDarkMatter(directory, options);
28691
+ darkMatterPairs = await _internals21.detectDarkMatter(directory, options);
28329
28692
  } catch (err) {
28330
28693
  const errMsg = err instanceof Error ? err.message : String(err);
28331
28694
  return `## Simulate Report
@@ -28358,7 +28721,16 @@ Ensure this is a git repository with commit history.`;
28358
28721
  const path55 = await import("path");
28359
28722
  const reportPath = path55.join(directory, ".swarm", "simulate-report.md");
28360
28723
  await fs29.mkdir(path55.dirname(reportPath), { recursive: true });
28361
- await fs29.writeFile(reportPath, report, "utf-8");
28724
+ const reportTempPath = path55.join(path55.dirname(reportPath), `${path55.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
28725
+ try {
28726
+ await fs29.writeFile(reportTempPath, report, "utf-8");
28727
+ renameSync11(reportTempPath, reportPath);
28728
+ } catch (err) {
28729
+ try {
28730
+ unlinkSync11(reportTempPath);
28731
+ } catch {}
28732
+ throw err;
28733
+ }
28362
28734
  } catch (err) {
28363
28735
  const writeErr = err instanceof Error ? err.message : String(err);
28364
28736
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -28581,7 +28953,7 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
28581
28953
  };
28582
28954
 
28583
28955
  // src/services/status-service.ts
28584
- var _internals42 = {
28956
+ var _internals43 = {
28585
28957
  loadLeanTurboRunState,
28586
28958
  hasActiveLeanTurbo,
28587
28959
  hasActiveFullAuto
@@ -28686,7 +29058,7 @@ async function getStatusData(directory, agents) {
28686
29058
  }
28687
29059
  function enrichWithLeanTurbo(status, directory) {
28688
29060
  const turboMode = hasActiveTurboMode();
28689
- const leanActive = _internals42.hasActiveLeanTurbo();
29061
+ const leanActive = _internals43.hasActiveLeanTurbo();
28690
29062
  let turboStrategy = "off";
28691
29063
  if (leanActive) {
28692
29064
  turboStrategy = "lean";
@@ -28705,7 +29077,7 @@ function enrichWithLeanTurbo(status, directory) {
28705
29077
  }
28706
29078
  }
28707
29079
  if (leanSessionID) {
28708
- const runState = _internals42.loadLeanTurboRunState(directory, leanSessionID);
29080
+ const runState = _internals43.loadLeanTurboRunState(directory, leanSessionID);
28709
29081
  if (runState) {
28710
29082
  status.leanTurboPhase = runState.phase;
28711
29083
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -28737,7 +29109,7 @@ function enrichWithLeanTurbo(status, directory) {
28737
29109
  }
28738
29110
  }
28739
29111
  }
28740
- status.fullAutoActive = _internals42.hasActiveFullAuto();
29112
+ status.fullAutoActive = _internals43.hasActiveFullAuto();
28741
29113
  return status;
28742
29114
  }
28743
29115
  function formatStatusMarkdown(status) {
@@ -28891,7 +29263,7 @@ No active swarm plan found. Nothing to sync.`;
28891
29263
 
28892
29264
  // src/commands/turbo.ts
28893
29265
  init_logger();
28894
- var _internals43 = {
29266
+ var _internals44 = {
28895
29267
  loadPluginConfigWithMeta
28896
29268
  };
28897
29269
  async function handleTurboCommand(directory, args, sessionID) {
@@ -28951,7 +29323,7 @@ async function handleTurboCommand(directory, args, sessionID) {
28951
29323
  if (arg0 === "on") {
28952
29324
  let strategy = "standard";
28953
29325
  try {
28954
- const { config } = _internals43.loadPluginConfigWithMeta(directory);
29326
+ const { config } = _internals44.loadPluginConfigWithMeta(directory);
28955
29327
  if (config.turbo?.strategy === "lean") {
28956
29328
  strategy = "lean";
28957
29329
  }
@@ -29048,7 +29420,7 @@ function enableLeanTurbo(session, directory, sessionID) {
29048
29420
  let maxParallelCoders = 4;
29049
29421
  let conflictPolicy = "serialize";
29050
29422
  try {
29051
- const { config } = _internals43.loadPluginConfigWithMeta(directory);
29423
+ const { config } = _internals44.loadPluginConfigWithMeta(directory);
29052
29424
  const leanConfig = config.turbo?.lean;
29053
29425
  if (leanConfig) {
29054
29426
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -29204,7 +29576,7 @@ function findSimilarCommands(query) {
29204
29576
  }
29205
29577
  const scored = VALID_COMMANDS.map((cmd) => {
29206
29578
  const cmdLower = cmd.toLowerCase();
29207
- const fullScore = _internals44.levenshteinDistance(q, cmdLower);
29579
+ const fullScore = _internals45.levenshteinDistance(q, cmdLower);
29208
29580
  let tokenScore = Infinity;
29209
29581
  if (cmd.includes(" ") || cmd.includes("-")) {
29210
29582
  const qTokens = q.split(/[\s-]+/);
@@ -29217,7 +29589,7 @@ function findSimilarCommands(query) {
29217
29589
  for (const ct of cmdTokens) {
29218
29590
  if (ct.length === 0)
29219
29591
  continue;
29220
- const dist = _internals44.levenshteinDistance(qt, ct);
29592
+ const dist = _internals45.levenshteinDistance(qt, ct);
29221
29593
  if (dist < minDist)
29222
29594
  minDist = dist;
29223
29595
  }
@@ -29227,7 +29599,7 @@ function findSimilarCommands(query) {
29227
29599
  }
29228
29600
  const dashStrippedQ = q.replace(/-/g, "");
29229
29601
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
29230
- const dashScore = _internals44.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
29602
+ const dashScore = _internals45.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
29231
29603
  const score = Math.min(fullScore, tokenScore, dashScore);
29232
29604
  return { cmd, score };
29233
29605
  });
@@ -29255,16 +29627,16 @@ function buildDetailedHelp(commandName, entry) {
29255
29627
  async function handleHelpCommand(ctx) {
29256
29628
  const targetCommand = ctx.args.join(" ");
29257
29629
  if (!targetCommand) {
29258
- const { buildHelpText } = await import("./index-dsjyfd3g.js");
29630
+ const { buildHelpText } = await import("./index-r3f47swm.js");
29259
29631
  return buildHelpText();
29260
29632
  }
29261
29633
  const tokens = targetCommand.split(/\s+/);
29262
- const resolved = _internals44.resolveCommand(tokens);
29634
+ const resolved = _internals45.resolveCommand(tokens);
29263
29635
  if (resolved) {
29264
- return _internals44.buildDetailedHelp(resolved.key, resolved.entry);
29636
+ return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
29265
29637
  }
29266
- const similar = _internals44.findSimilarCommands(targetCommand);
29267
- const { buildHelpText: fullHelp } = await import("./index-dsjyfd3g.js");
29638
+ const similar = _internals45.findSimilarCommands(targetCommand);
29639
+ const { buildHelpText: fullHelp } = await import("./index-r3f47swm.js");
29268
29640
  if (similar.length > 0) {
29269
29641
  return `Command '/swarm ${targetCommand}' not found.
29270
29642
 
@@ -29328,7 +29700,7 @@ var COMMAND_REGISTRY = {
29328
29700
  toolNoArgs: true
29329
29701
  },
29330
29702
  help: {
29331
- handler: (ctx) => _internals44.handleHelpCommand(ctx),
29703
+ handler: (ctx) => _internals45.handleHelpCommand(ctx),
29332
29704
  description: "Show help for swarm commands",
29333
29705
  category: "core",
29334
29706
  args: "[command]",
@@ -29397,7 +29769,7 @@ var COMMAND_REGISTRY = {
29397
29769
  },
29398
29770
  "guardrail explain": {
29399
29771
  handler: async (ctx) => {
29400
- const { handleGuardrailExplain } = await import("./guardrail-explain-scym5r5y.js");
29772
+ const { handleGuardrailExplain } = await import("./guardrail-explain-2q9myk7c.js");
29401
29773
  return handleGuardrailExplain(ctx.directory, ctx.args);
29402
29774
  },
29403
29775
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -30178,7 +30550,7 @@ function validateToolPolicy() {
30178
30550
  }
30179
30551
  return { valid: warnings.length === 0, warnings };
30180
30552
  }
30181
- var _internals44 = {
30553
+ var _internals45 = {
30182
30554
  handleHelpCommand,
30183
30555
  validateAliases,
30184
30556
  validateToolPolicy,
@@ -30187,7 +30559,7 @@ var _internals44 = {
30187
30559
  findSimilarCommands,
30188
30560
  buildDetailedHelp
30189
30561
  };
30190
- var validation = _internals44.validateAliases();
30562
+ var validation = _internals45.validateAliases();
30191
30563
  if (!validation.valid) {
30192
30564
  throw new Error(`COMMAND_REGISTRY alias validation failed:
30193
30565
  ${validation.errors.join(`
@@ -30199,7 +30571,7 @@ ${validation.warnings.join(`
30199
30571
  `)}`);
30200
30572
  }
30201
30573
  try {
30202
- const toolPolicyValidation = _internals44.validateToolPolicy();
30574
+ const toolPolicyValidation = _internals45.validateToolPolicy();
30203
30575
  if (toolPolicyValidation.warnings.length > 0) {
30204
30576
  console.warn(`COMMAND_REGISTRY toolPolicy warnings:
30205
30577
  ${toolPolicyValidation.warnings.join(`
@@ -30263,7 +30635,7 @@ function formatCommandNotFound(tokens) {
30263
30635
  const attemptedCommand = tokens[0] || "";
30264
30636
  const MAX_DISPLAY = 100;
30265
30637
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
30266
- const similar = _internals44.findSimilarCommands(attemptedCommand);
30638
+ const similar = _internals45.findSimilarCommands(attemptedCommand);
30267
30639
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
30268
30640
  const suggestions = similar.length > 0 ? `Did you mean:
30269
30641
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -30320,4 +30692,4 @@ ${text}`;
30320
30692
  };
30321
30693
  }
30322
30694
 
30323
- export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals44 as _internals, resolveCommand };
30695
+ export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals45 as _internals, resolveCommand };