opencode-swarm 6.43.1 → 6.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -16125,9 +16125,278 @@ var require_proper_lockfile = __commonJS((exports, module) => {
16125
16125
  module.exports.checkSync = checkSync;
16126
16126
  });
16127
16127
 
16128
+ // src/plan/ledger.ts
16129
+ import * as crypto2 from "crypto";
16130
+ import * as fs4 from "fs";
16131
+ import * as path7 from "path";
16132
+ function getLedgerPath(directory) {
16133
+ return path7.join(directory, ".swarm", LEDGER_FILENAME);
16134
+ }
16135
+ function getPlanJsonPath(directory) {
16136
+ return path7.join(directory, ".swarm", PLAN_JSON_FILENAME);
16137
+ }
16138
+ function computePlanHash(plan) {
16139
+ const normalized = {
16140
+ schema_version: plan.schema_version,
16141
+ title: plan.title,
16142
+ swarm: plan.swarm,
16143
+ current_phase: plan.current_phase,
16144
+ migration_status: plan.migration_status,
16145
+ phases: plan.phases.map((phase) => ({
16146
+ id: phase.id,
16147
+ name: phase.name,
16148
+ status: phase.status,
16149
+ required_agents: phase.required_agents ? [...phase.required_agents].sort() : undefined,
16150
+ tasks: phase.tasks.map((task) => ({
16151
+ id: task.id,
16152
+ phase: task.phase,
16153
+ status: task.status,
16154
+ size: task.size,
16155
+ description: task.description,
16156
+ depends: [...task.depends].sort(),
16157
+ acceptance: task.acceptance,
16158
+ files_touched: [...task.files_touched].sort(),
16159
+ evidence_path: task.evidence_path,
16160
+ blocked_reason: task.blocked_reason
16161
+ }))
16162
+ }))
16163
+ };
16164
+ const jsonString = JSON.stringify(normalized);
16165
+ return crypto2.createHash("sha256").update(jsonString, "utf8").digest("hex");
16166
+ }
16167
+ function computeCurrentPlanHash(directory) {
16168
+ const planPath = getPlanJsonPath(directory);
16169
+ try {
16170
+ const content = fs4.readFileSync(planPath, "utf8");
16171
+ const plan = JSON.parse(content);
16172
+ return computePlanHash(plan);
16173
+ } catch {
16174
+ return "";
16175
+ }
16176
+ }
16177
+ async function ledgerExists(directory) {
16178
+ const ledgerPath = getLedgerPath(directory);
16179
+ return fs4.existsSync(ledgerPath);
16180
+ }
16181
+ async function getLatestLedgerSeq(directory) {
16182
+ const ledgerPath = getLedgerPath(directory);
16183
+ if (!fs4.existsSync(ledgerPath)) {
16184
+ return 0;
16185
+ }
16186
+ try {
16187
+ const content = fs4.readFileSync(ledgerPath, "utf8");
16188
+ const lines = content.trim().split(`
16189
+ `).filter((line) => line.trim() !== "");
16190
+ if (lines.length === 0) {
16191
+ return 0;
16192
+ }
16193
+ let maxSeq = 0;
16194
+ for (const line of lines) {
16195
+ try {
16196
+ const event = JSON.parse(line);
16197
+ if (event.seq > maxSeq) {
16198
+ maxSeq = event.seq;
16199
+ }
16200
+ } catch {}
16201
+ }
16202
+ return maxSeq;
16203
+ } catch {
16204
+ return 0;
16205
+ }
16206
+ }
16207
+ async function readLedgerEvents(directory) {
16208
+ const ledgerPath = getLedgerPath(directory);
16209
+ if (!fs4.existsSync(ledgerPath)) {
16210
+ return [];
16211
+ }
16212
+ try {
16213
+ const content = fs4.readFileSync(ledgerPath, "utf8");
16214
+ const lines = content.trim().split(`
16215
+ `).filter((line) => line.trim() !== "");
16216
+ const events = [];
16217
+ for (const line of lines) {
16218
+ try {
16219
+ const event = JSON.parse(line);
16220
+ events.push(event);
16221
+ } catch {}
16222
+ }
16223
+ events.sort((a, b) => a.seq - b.seq);
16224
+ return events;
16225
+ } catch {
16226
+ return [];
16227
+ }
16228
+ }
16229
+ async function initLedger(directory, planId) {
16230
+ const ledgerPath = getLedgerPath(directory);
16231
+ const planJsonPath = getPlanJsonPath(directory);
16232
+ if (fs4.existsSync(ledgerPath)) {
16233
+ throw new Error("Ledger already initialized. Use appendLedgerEvent to add events.");
16234
+ }
16235
+ let planHashAfter = "";
16236
+ try {
16237
+ if (fs4.existsSync(planJsonPath)) {
16238
+ const content = fs4.readFileSync(planJsonPath, "utf8");
16239
+ const plan = JSON.parse(content);
16240
+ planHashAfter = computePlanHash(plan);
16241
+ }
16242
+ } catch {}
16243
+ const event = {
16244
+ seq: 1,
16245
+ timestamp: new Date().toISOString(),
16246
+ plan_id: planId,
16247
+ event_type: "plan_created",
16248
+ source: "initLedger",
16249
+ plan_hash_before: "",
16250
+ plan_hash_after: planHashAfter,
16251
+ schema_version: LEDGER_SCHEMA_VERSION
16252
+ };
16253
+ fs4.mkdirSync(path7.join(directory, ".swarm"), { recursive: true });
16254
+ const tempPath = `${ledgerPath}.tmp`;
16255
+ const line = `${JSON.stringify(event)}
16256
+ `;
16257
+ fs4.writeFileSync(tempPath, line, "utf8");
16258
+ fs4.renameSync(tempPath, ledgerPath);
16259
+ }
16260
+ async function appendLedgerEvent(directory, eventInput, options) {
16261
+ const ledgerPath = getLedgerPath(directory);
16262
+ const latestSeq = await getLatestLedgerSeq(directory);
16263
+ const nextSeq = latestSeq + 1;
16264
+ const planHashBefore = computeCurrentPlanHash(directory);
16265
+ if (options?.expectedSeq !== undefined && options.expectedSeq !== latestSeq) {
16266
+ throw new LedgerStaleWriterError(`Stale writer: expected seq ${options.expectedSeq} but found ${latestSeq}`);
16267
+ }
16268
+ if (options?.expectedHash !== undefined && options.expectedHash !== planHashBefore) {
16269
+ throw new LedgerStaleWriterError(`Stale writer: expected hash ${options.expectedHash} but found ${planHashBefore}`);
16270
+ }
16271
+ const planHashAfter = options?.planHashAfter ?? planHashBefore;
16272
+ const event = {
16273
+ ...eventInput,
16274
+ seq: nextSeq,
16275
+ timestamp: new Date().toISOString(),
16276
+ plan_hash_before: planHashBefore,
16277
+ plan_hash_after: planHashAfter,
16278
+ schema_version: LEDGER_SCHEMA_VERSION
16279
+ };
16280
+ fs4.mkdirSync(path7.join(directory, ".swarm"), { recursive: true });
16281
+ const tempPath = `${ledgerPath}.tmp`;
16282
+ const line = `${JSON.stringify(event)}
16283
+ `;
16284
+ if (fs4.existsSync(ledgerPath)) {
16285
+ const existingContent = fs4.readFileSync(ledgerPath, "utf8");
16286
+ fs4.writeFileSync(tempPath, existingContent + line, "utf8");
16287
+ } else {
16288
+ throw new Error("Ledger not initialized. Call initLedger() first.");
16289
+ }
16290
+ fs4.renameSync(tempPath, ledgerPath);
16291
+ return event;
16292
+ }
16293
+ async function takeSnapshotEvent(directory, plan, options) {
16294
+ const payloadHash = computePlanHash(plan);
16295
+ const snapshotPayload = {
16296
+ plan,
16297
+ payload_hash: payloadHash
16298
+ };
16299
+ return appendLedgerEvent(directory, {
16300
+ event_type: "snapshot",
16301
+ source: "takeSnapshotEvent",
16302
+ plan_id: plan.title,
16303
+ payload: snapshotPayload
16304
+ }, options);
16305
+ }
16306
+ async function replayFromLedger(directory, options) {
16307
+ const events = await readLedgerEvents(directory);
16308
+ if (events.length === 0) {
16309
+ return null;
16310
+ }
16311
+ {
16312
+ const snapshotEvents = events.filter((e) => e.event_type === "snapshot");
16313
+ if (snapshotEvents.length > 0) {
16314
+ const latestSnapshotEvent = snapshotEvents[snapshotEvents.length - 1];
16315
+ const snapshotPayload = latestSnapshotEvent.payload;
16316
+ let plan2 = snapshotPayload.plan;
16317
+ const eventsAfterSnapshot = events.filter((e) => e.seq > latestSnapshotEvent.seq);
16318
+ for (const event of eventsAfterSnapshot) {
16319
+ plan2 = applyEventToPlan(plan2, event);
16320
+ if (plan2 === null) {
16321
+ return null;
16322
+ }
16323
+ }
16324
+ return plan2;
16325
+ }
16326
+ }
16327
+ const planJsonPath = getPlanJsonPath(directory);
16328
+ if (!fs4.existsSync(planJsonPath)) {
16329
+ return null;
16330
+ }
16331
+ let plan;
16332
+ try {
16333
+ const content = fs4.readFileSync(planJsonPath, "utf8");
16334
+ plan = JSON.parse(content);
16335
+ } catch {
16336
+ return null;
16337
+ }
16338
+ for (const event of events) {
16339
+ if (plan === null) {
16340
+ return null;
16341
+ }
16342
+ plan = applyEventToPlan(plan, event);
16343
+ }
16344
+ return plan;
16345
+ }
16346
+ function applyEventToPlan(plan, event) {
16347
+ switch (event.event_type) {
16348
+ case "plan_created":
16349
+ return plan;
16350
+ case "task_status_changed":
16351
+ if (event.task_id && event.to_status) {
16352
+ for (const phase of plan.phases) {
16353
+ const task = phase.tasks.find((t) => t.id === event.task_id);
16354
+ if (task) {
16355
+ task.status = event.to_status;
16356
+ break;
16357
+ }
16358
+ }
16359
+ }
16360
+ return plan;
16361
+ case "phase_completed":
16362
+ if (event.phase_id) {
16363
+ const phase = plan.phases.find((p) => p.id === event.phase_id);
16364
+ if (phase) {
16365
+ phase.status = "complete";
16366
+ }
16367
+ }
16368
+ return plan;
16369
+ case "plan_exported":
16370
+ return plan;
16371
+ case "task_added":
16372
+ return plan;
16373
+ case "task_updated":
16374
+ return plan;
16375
+ case "plan_rebuilt":
16376
+ return plan;
16377
+ case "task_reordered":
16378
+ return plan;
16379
+ case "snapshot":
16380
+ return plan;
16381
+ case "plan_reset":
16382
+ return null;
16383
+ default:
16384
+ throw new Error(`applyEventToPlan: unhandled event type "${event.event_type}" at seq ${event.seq}`);
16385
+ }
16386
+ }
16387
+ var LEDGER_SCHEMA_VERSION = "1.0.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
16388
+ var init_ledger = __esm(() => {
16389
+ LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
16390
+ constructor(message) {
16391
+ super(message);
16392
+ this.name = "LedgerStaleWriterError";
16393
+ }
16394
+ };
16395
+ });
16396
+
16128
16397
  // src/plan/manager.ts
16129
16398
  import { renameSync as renameSync3, unlinkSync } from "fs";
16130
- import * as path12 from "path";
16399
+ import * as path8 from "path";
16131
16400
  async function loadPlanJsonOnly(directory) {
16132
16401
  const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
16133
16402
  if (planJsonContent !== null) {
@@ -16158,6 +16427,17 @@ function compareTaskIds(a, b) {
16158
16427
  }
16159
16428
  return 0;
16160
16429
  }
16430
+ async function getLatestLedgerHash(directory) {
16431
+ try {
16432
+ const events = await readLedgerEvents(directory);
16433
+ if (events.length === 0)
16434
+ return "";
16435
+ const lastEvent = events[events.length - 1];
16436
+ return lastEvent.plan_hash_after;
16437
+ } catch {
16438
+ return "";
16439
+ }
16440
+ }
16161
16441
  function computePlanContentHash(plan) {
16162
16442
  const content = {
16163
16443
  schema_version: plan.schema_version,
@@ -16209,13 +16489,13 @@ async function isPlanMdInSync(directory, plan) {
16209
16489
  return normalizedActual.includes(normalizedExpected) || normalizedExpected.includes(normalizedActual.replace(/^#.*$/gm, "").trim());
16210
16490
  }
16211
16491
  async function regeneratePlanMarkdown(directory, plan) {
16212
- const swarmDir = path12.resolve(directory, ".swarm");
16492
+ const swarmDir = path8.resolve(directory, ".swarm");
16213
16493
  const contentHash = computePlanContentHash(plan);
16214
16494
  const markdown = derivePlanMarkdown(plan);
16215
16495
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16216
16496
  ${markdown}`;
16217
- const mdPath = path12.join(swarmDir, "plan.md");
16218
- const mdTempPath = path12.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16497
+ const mdPath = path8.join(swarmDir, "plan.md");
16498
+ const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16219
16499
  try {
16220
16500
  await Bun.write(mdTempPath, markdownWithHash);
16221
16501
  renameSync3(mdTempPath, mdPath);
@@ -16242,9 +16522,34 @@ async function loadPlan(directory) {
16242
16522
  warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
16243
16523
  }
16244
16524
  }
16525
+ if (await ledgerExists(directory)) {
16526
+ const planHash = computePlanHash(validated);
16527
+ const ledgerHash = await getLatestLedgerHash(directory);
16528
+ if (ledgerHash !== "" && planHash !== ledgerHash) {
16529
+ warn("[loadPlan] plan.json is stale (hash mismatch with ledger) \u2014 rebuilding from ledger. If this recurs, run /swarm reset-session to clear stale session state.");
16530
+ try {
16531
+ const rebuilt = await replayFromLedger(directory);
16532
+ if (rebuilt) {
16533
+ await rebuildPlan(directory, rebuilt);
16534
+ warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at SWARM_PLAN.md if it exists.");
16535
+ return rebuilt;
16536
+ }
16537
+ } catch (replayError) {
16538
+ warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error ? replayError.message : String(replayError)}. Returning stale plan.json. To recover: check SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`);
16539
+ }
16540
+ }
16541
+ }
16245
16542
  return validated;
16246
16543
  } catch (error93) {
16247
- warn(`Plan validation failed for .swarm/plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`);
16544
+ warn(`[loadPlan] plan.json validation failed: ${error93 instanceof Error ? error93.message : String(error93)}. Attempting rebuild from ledger. If rebuild fails, check SWARM_PLAN.md for a checkpoint.`);
16545
+ if (await ledgerExists(directory)) {
16546
+ const rebuilt = await replayFromLedger(directory);
16547
+ if (rebuilt) {
16548
+ await rebuildPlan(directory, rebuilt);
16549
+ warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale.");
16550
+ return rebuilt;
16551
+ }
16552
+ }
16248
16553
  const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
16249
16554
  if (planMdContent2 !== null) {
16250
16555
  const migrated = migrateLegacyPlan(planMdContent2);
@@ -16260,6 +16565,13 @@ async function loadPlan(directory) {
16260
16565
  await savePlan(directory, migrated);
16261
16566
  return migrated;
16262
16567
  }
16568
+ if (await ledgerExists(directory)) {
16569
+ const rebuilt = await replayFromLedger(directory);
16570
+ if (rebuilt) {
16571
+ await savePlan(directory, rebuilt);
16572
+ return rebuilt;
16573
+ }
16574
+ }
16263
16575
  return null;
16264
16576
  }
16265
16577
  async function savePlan(directory, plan, options) {
@@ -16269,10 +16581,10 @@ async function savePlan(directory, plan, options) {
16269
16581
  const validated = PlanSchema.parse(plan);
16270
16582
  if (options?.preserveCompletedStatuses !== false) {
16271
16583
  try {
16272
- const currentPlan = await loadPlanJsonOnly(directory);
16273
- if (currentPlan) {
16584
+ const currentPlan2 = await loadPlanJsonOnly(directory);
16585
+ if (currentPlan2) {
16274
16586
  const completedTaskIds = new Set;
16275
- for (const phase of currentPlan.phases) {
16587
+ for (const phase of currentPlan2.phases) {
16276
16588
  for (const task of phase.tasks) {
16277
16589
  if (task.status === "completed")
16278
16590
  completedTaskIds.add(task.id);
@@ -16302,9 +16614,58 @@ async function savePlan(directory, plan, options) {
16302
16614
  phase.status = "pending";
16303
16615
  }
16304
16616
  }
16305
- const swarmDir = path12.resolve(directory, ".swarm");
16306
- const planPath = path12.join(swarmDir, "plan.json");
16307
- const tempPath = path12.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16617
+ const currentPlan = await loadPlanJsonOnly(directory);
16618
+ if (!await ledgerExists(directory)) {
16619
+ const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16620
+ await initLedger(directory, planId);
16621
+ }
16622
+ const currentHash = computeCurrentPlanHash(directory);
16623
+ const hashAfter = computePlanHash(validated);
16624
+ if (currentPlan) {
16625
+ const oldTaskMap = new Map;
16626
+ for (const phase of currentPlan.phases) {
16627
+ for (const task of phase.tasks) {
16628
+ oldTaskMap.set(task.id, { phase: task.phase, status: task.status });
16629
+ }
16630
+ }
16631
+ try {
16632
+ for (const phase of validated.phases) {
16633
+ for (const task of phase.tasks) {
16634
+ const oldTask = oldTaskMap.get(task.id);
16635
+ if (oldTask && oldTask.status !== task.status) {
16636
+ const eventInput = {
16637
+ plan_id: `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_"),
16638
+ event_type: "task_status_changed",
16639
+ task_id: task.id,
16640
+ phase_id: phase.id,
16641
+ from_status: oldTask.status,
16642
+ to_status: task.status,
16643
+ source: "savePlan"
16644
+ };
16645
+ await appendLedgerEvent(directory, eventInput, {
16646
+ expectedHash: currentHash,
16647
+ planHashAfter: hashAfter
16648
+ });
16649
+ }
16650
+ }
16651
+ }
16652
+ } catch (error93) {
16653
+ if (error93 instanceof LedgerStaleWriterError) {
16654
+ throw new Error(`Concurrent plan modification detected: ${error93.message}. Please retry the operation.`);
16655
+ }
16656
+ throw error93;
16657
+ }
16658
+ }
16659
+ const SNAPSHOT_INTERVAL = 50;
16660
+ const latestSeq = await getLatestLedgerSeq(directory);
16661
+ if (latestSeq > 0 && latestSeq % SNAPSHOT_INTERVAL === 0) {
16662
+ await takeSnapshotEvent(directory, validated, {
16663
+ planHashAfter: hashAfter
16664
+ }).catch(() => {});
16665
+ }
16666
+ const swarmDir = path8.resolve(directory, ".swarm");
16667
+ const planPath = path8.join(swarmDir, "plan.json");
16668
+ const tempPath = path8.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16308
16669
  try {
16309
16670
  await Bun.write(tempPath, JSON.stringify(validated, null, 2));
16310
16671
  renameSync3(tempPath, planPath);
@@ -16317,8 +16678,8 @@ async function savePlan(directory, plan, options) {
16317
16678
  const markdown = derivePlanMarkdown(validated);
16318
16679
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16319
16680
  ${markdown}`;
16320
- const mdPath = path12.join(swarmDir, "plan.md");
16321
- const mdTempPath = path12.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16681
+ const mdPath = path8.join(swarmDir, "plan.md");
16682
+ const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16322
16683
  try {
16323
16684
  await Bun.write(mdTempPath, markdownWithHash);
16324
16685
  renameSync3(mdTempPath, mdPath);
@@ -16328,7 +16689,7 @@ ${markdown}`;
16328
16689
  } catch {}
16329
16690
  }
16330
16691
  try {
16331
- const markerPath = path12.join(swarmDir, ".plan-write-marker");
16692
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
16332
16693
  const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
16333
16694
  const marker = JSON.stringify({
16334
16695
  source: "plan_manager",
@@ -16339,6 +16700,22 @@ ${markdown}`;
16339
16700
  await Bun.write(markerPath, marker);
16340
16701
  } catch {}
16341
16702
  }
16703
+ async function rebuildPlan(directory, plan) {
16704
+ const targetPlan = plan ?? await replayFromLedger(directory);
16705
+ if (!targetPlan)
16706
+ return null;
16707
+ const swarmDir = path8.join(directory, ".swarm");
16708
+ const planPath = path8.join(swarmDir, "plan.json");
16709
+ const mdPath = path8.join(swarmDir, "plan.md");
16710
+ const tempPlanPath = path8.join(swarmDir, `plan.json.rebuild.${Date.now()}`);
16711
+ await Bun.write(tempPlanPath, JSON.stringify(targetPlan, null, 2));
16712
+ renameSync3(tempPlanPath, planPath);
16713
+ const markdown = derivePlanMarkdown(targetPlan);
16714
+ const tempMdPath = path8.join(swarmDir, `plan.md.rebuild.${Date.now()}`);
16715
+ await Bun.write(tempMdPath, markdown);
16716
+ renameSync3(tempMdPath, mdPath);
16717
+ return targetPlan;
16718
+ }
16342
16719
  function derivePlanMarkdown(plan) {
16343
16720
  const statusMap = {
16344
16721
  pending: "PENDING",
@@ -16609,6 +16986,7 @@ var init_manager2 = __esm(() => {
16609
16986
  init_plan_schema();
16610
16987
  init_utils2();
16611
16988
  init_utils();
16989
+ init_ledger();
16612
16990
  });
16613
16991
 
16614
16992
  // src/services/config-doctor.ts
@@ -16624,20 +17002,20 @@ __export(exports_config_doctor, {
16624
17002
  createConfigBackup: () => createConfigBackup,
16625
17003
  applySafeAutoFixes: () => applySafeAutoFixes
16626
17004
  });
16627
- import * as crypto2 from "crypto";
16628
- import * as fs5 from "fs";
17005
+ import * as crypto3 from "crypto";
17006
+ import * as fs7 from "fs";
16629
17007
  import * as os4 from "os";
16630
- import * as path14 from "path";
17008
+ import * as path16 from "path";
16631
17009
  function getUserConfigDir3() {
16632
- return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
17010
+ return process.env.XDG_CONFIG_HOME || path16.join(os4.homedir(), ".config");
16633
17011
  }
16634
17012
  function getConfigPaths(directory) {
16635
- const userConfigPath = path14.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
16636
- const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
17013
+ const userConfigPath = path16.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17014
+ const projectConfigPath = path16.join(directory, ".opencode", "opencode-swarm.json");
16637
17015
  return { userConfigPath, projectConfigPath };
16638
17016
  }
16639
17017
  function computeHash(content) {
16640
- return crypto2.createHash("sha256").update(content, "utf-8").digest("hex");
17018
+ return crypto3.createHash("sha256").update(content, "utf-8").digest("hex");
16641
17019
  }
16642
17020
  function isValidConfigPath(configPath, directory) {
16643
17021
  const normalizedPath = configPath.replace(/\\/g, "/");
@@ -16658,9 +17036,9 @@ function isValidConfigPath(configPath, directory) {
16658
17036
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
16659
17037
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
16660
17038
  try {
16661
- const resolvedConfig = path14.resolve(configPath);
16662
- const resolvedUser = path14.resolve(normalizedUser);
16663
- const resolvedProject = path14.resolve(normalizedProject);
17039
+ const resolvedConfig = path16.resolve(configPath);
17040
+ const resolvedUser = path16.resolve(normalizedUser);
17041
+ const resolvedProject = path16.resolve(normalizedProject);
16664
17042
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
16665
17043
  } catch {
16666
17044
  return false;
@@ -16670,19 +17048,19 @@ function createConfigBackup(directory) {
16670
17048
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
16671
17049
  let configPath = projectConfigPath;
16672
17050
  let content = null;
16673
- if (fs5.existsSync(projectConfigPath)) {
17051
+ if (fs7.existsSync(projectConfigPath)) {
16674
17052
  try {
16675
- content = fs5.readFileSync(projectConfigPath, "utf-8");
17053
+ content = fs7.readFileSync(projectConfigPath, "utf-8");
16676
17054
  } catch (error93) {
16677
17055
  log("[ConfigDoctor] project config read failed", {
16678
17056
  error: error93 instanceof Error ? error93.message : String(error93)
16679
17057
  });
16680
17058
  }
16681
17059
  }
16682
- if (content === null && fs5.existsSync(userConfigPath)) {
17060
+ if (content === null && fs7.existsSync(userConfigPath)) {
16683
17061
  configPath = userConfigPath;
16684
17062
  try {
16685
- content = fs5.readFileSync(userConfigPath, "utf-8");
17063
+ content = fs7.readFileSync(userConfigPath, "utf-8");
16686
17064
  } catch (error93) {
16687
17065
  log("[ConfigDoctor] user config read failed", {
16688
17066
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -16700,12 +17078,12 @@ function createConfigBackup(directory) {
16700
17078
  };
16701
17079
  }
16702
17080
  function writeBackupArtifact(directory, backup) {
16703
- const swarmDir = path14.join(directory, ".swarm");
16704
- if (!fs5.existsSync(swarmDir)) {
16705
- fs5.mkdirSync(swarmDir, { recursive: true });
17081
+ const swarmDir = path16.join(directory, ".swarm");
17082
+ if (!fs7.existsSync(swarmDir)) {
17083
+ fs7.mkdirSync(swarmDir, { recursive: true });
16706
17084
  }
16707
17085
  const backupFilename = `config-backup-${backup.createdAt}.json`;
16708
- const backupPath = path14.join(swarmDir, backupFilename);
17086
+ const backupPath = path16.join(swarmDir, backupFilename);
16709
17087
  const artifact = {
16710
17088
  createdAt: backup.createdAt,
16711
17089
  configPath: backup.configPath,
@@ -16713,15 +17091,15 @@ function writeBackupArtifact(directory, backup) {
16713
17091
  content: backup.content,
16714
17092
  preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
16715
17093
  };
16716
- fs5.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
17094
+ fs7.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
16717
17095
  return backupPath;
16718
17096
  }
16719
17097
  function restoreFromBackup(backupPath, directory) {
16720
- if (!fs5.existsSync(backupPath)) {
17098
+ if (!fs7.existsSync(backupPath)) {
16721
17099
  return null;
16722
17100
  }
16723
17101
  try {
16724
- const artifact = JSON.parse(fs5.readFileSync(backupPath, "utf-8"));
17102
+ const artifact = JSON.parse(fs7.readFileSync(backupPath, "utf-8"));
16725
17103
  if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
16726
17104
  return null;
16727
17105
  }
@@ -16735,11 +17113,11 @@ function restoreFromBackup(backupPath, directory) {
16735
17113
  return null;
16736
17114
  }
16737
17115
  const targetPath = artifact.configPath;
16738
- const targetDir = path14.dirname(targetPath);
16739
- if (!fs5.existsSync(targetDir)) {
16740
- fs5.mkdirSync(targetDir, { recursive: true });
17116
+ const targetDir = path16.dirname(targetPath);
17117
+ if (!fs7.existsSync(targetDir)) {
17118
+ fs7.mkdirSync(targetDir, { recursive: true });
16741
17119
  }
16742
- fs5.writeFileSync(targetPath, artifact.content, "utf-8");
17120
+ fs7.writeFileSync(targetPath, artifact.content, "utf-8");
16743
17121
  return targetPath;
16744
17122
  } catch {
16745
17123
  return null;
@@ -16749,12 +17127,12 @@ function readConfigFromFile(directory) {
16749
17127
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
16750
17128
  let configPath = projectConfigPath;
16751
17129
  let configContent = null;
16752
- if (fs5.existsSync(projectConfigPath)) {
17130
+ if (fs7.existsSync(projectConfigPath)) {
16753
17131
  configPath = projectConfigPath;
16754
- configContent = fs5.readFileSync(projectConfigPath, "utf-8");
16755
- } else if (fs5.existsSync(userConfigPath)) {
17132
+ configContent = fs7.readFileSync(projectConfigPath, "utf-8");
17133
+ } else if (fs7.existsSync(userConfigPath)) {
16756
17134
  configPath = userConfigPath;
16757
- configContent = fs5.readFileSync(userConfigPath, "utf-8");
17135
+ configContent = fs7.readFileSync(userConfigPath, "utf-8");
16758
17136
  }
16759
17137
  if (configContent === null) {
16760
17138
  return null;
@@ -16766,9 +17144,9 @@ function readConfigFromFile(directory) {
16766
17144
  return null;
16767
17145
  }
16768
17146
  }
16769
- function validateConfigKey(path15, value, _config) {
17147
+ function validateConfigKey(path17, value, _config) {
16770
17148
  const findings = [];
16771
- switch (path15) {
17149
+ switch (path17) {
16772
17150
  case "agents": {
16773
17151
  if (value !== undefined) {
16774
17152
  findings.push({
@@ -17015,27 +17393,27 @@ function validateConfigKey(path15, value, _config) {
17015
17393
  }
17016
17394
  return findings;
17017
17395
  }
17018
- function walkConfigAndValidate(obj, path15, config3, findings) {
17396
+ function walkConfigAndValidate(obj, path17, config3, findings) {
17019
17397
  if (obj === null || obj === undefined) {
17020
17398
  return;
17021
17399
  }
17022
- if (path15 && typeof obj === "object" && !Array.isArray(obj)) {
17023
- const keyFindings = validateConfigKey(path15, obj, config3);
17400
+ if (path17 && typeof obj === "object" && !Array.isArray(obj)) {
17401
+ const keyFindings = validateConfigKey(path17, obj, config3);
17024
17402
  findings.push(...keyFindings);
17025
17403
  }
17026
17404
  if (typeof obj !== "object") {
17027
- const keyFindings = validateConfigKey(path15, obj, config3);
17405
+ const keyFindings = validateConfigKey(path17, obj, config3);
17028
17406
  findings.push(...keyFindings);
17029
17407
  return;
17030
17408
  }
17031
17409
  if (Array.isArray(obj)) {
17032
17410
  obj.forEach((item, index) => {
17033
- walkConfigAndValidate(item, `${path15}[${index}]`, config3, findings);
17411
+ walkConfigAndValidate(item, `${path17}[${index}]`, config3, findings);
17034
17412
  });
17035
17413
  return;
17036
17414
  }
17037
17415
  for (const [key, value] of Object.entries(obj)) {
17038
- const newPath = path15 ? `${path15}.${key}` : key;
17416
+ const newPath = path17 ? `${path17}.${key}` : key;
17039
17417
  walkConfigAndValidate(value, newPath, config3, findings);
17040
17418
  }
17041
17419
  }
@@ -17050,9 +17428,9 @@ function runConfigDoctor(config3, directory) {
17050
17428
  const hasAutoFixableIssues = findings.some((f) => f.autoFixable && f.proposedFix?.risk === "low");
17051
17429
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17052
17430
  let configSource = "defaults";
17053
- if (fs5.existsSync(projectConfigPath)) {
17431
+ if (fs7.existsSync(projectConfigPath)) {
17054
17432
  configSource = projectConfigPath;
17055
- } else if (fs5.existsSync(userConfigPath)) {
17433
+ } else if (fs7.existsSync(userConfigPath)) {
17056
17434
  configSource = userConfigPath;
17057
17435
  }
17058
17436
  return {
@@ -17081,12 +17459,12 @@ function applySafeAutoFixes(directory, result) {
17081
17459
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17082
17460
  let configPath = projectConfigPath;
17083
17461
  let configContent;
17084
- if (fs5.existsSync(projectConfigPath)) {
17462
+ if (fs7.existsSync(projectConfigPath)) {
17085
17463
  configPath = projectConfigPath;
17086
- configContent = fs5.readFileSync(projectConfigPath, "utf-8");
17087
- } else if (fs5.existsSync(userConfigPath)) {
17464
+ configContent = fs7.readFileSync(projectConfigPath, "utf-8");
17465
+ } else if (fs7.existsSync(userConfigPath)) {
17088
17466
  configPath = userConfigPath;
17089
- configContent = fs5.readFileSync(userConfigPath, "utf-8");
17467
+ configContent = fs7.readFileSync(userConfigPath, "utf-8");
17090
17468
  } else {
17091
17469
  return { appliedFixes, updatedConfigPath: null };
17092
17470
  }
@@ -17155,22 +17533,22 @@ function applySafeAutoFixes(directory, result) {
17155
17533
  }
17156
17534
  }
17157
17535
  if (appliedFixes.length > 0) {
17158
- const configDir = path14.dirname(configPath);
17159
- if (!fs5.existsSync(configDir)) {
17160
- fs5.mkdirSync(configDir, { recursive: true });
17536
+ const configDir = path16.dirname(configPath);
17537
+ if (!fs7.existsSync(configDir)) {
17538
+ fs7.mkdirSync(configDir, { recursive: true });
17161
17539
  }
17162
- fs5.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
17540
+ fs7.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
17163
17541
  updatedConfigPath = configPath;
17164
17542
  }
17165
17543
  return { appliedFixes, updatedConfigPath };
17166
17544
  }
17167
17545
  function writeDoctorArtifact(directory, result) {
17168
- const swarmDir = path14.join(directory, ".swarm");
17169
- if (!fs5.existsSync(swarmDir)) {
17170
- fs5.mkdirSync(swarmDir, { recursive: true });
17546
+ const swarmDir = path16.join(directory, ".swarm");
17547
+ if (!fs7.existsSync(swarmDir)) {
17548
+ fs7.mkdirSync(swarmDir, { recursive: true });
17171
17549
  }
17172
17550
  const artifactFilename = "config-doctor.json";
17173
- const artifactPath = path14.join(swarmDir, artifactFilename);
17551
+ const artifactPath = path16.join(swarmDir, artifactFilename);
17174
17552
  const guiOutput = {
17175
17553
  timestamp: result.timestamp,
17176
17554
  summary: result.summary,
@@ -17191,7 +17569,7 @@ function writeDoctorArtifact(directory, result) {
17191
17569
  } : null
17192
17570
  }))
17193
17571
  };
17194
- fs5.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
17572
+ fs7.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
17195
17573
  return artifactPath;
17196
17574
  }
17197
17575
  function shouldRunOnStartup(automationConfig) {
@@ -17531,9 +17909,9 @@ var init_evidence_summary_service = __esm(() => {
17531
17909
  });
17532
17910
 
17533
17911
  // src/cli/index.ts
17534
- import * as fs15 from "fs";
17912
+ import * as fs17 from "fs";
17535
17913
  import * as os5 from "os";
17536
- import * as path25 from "path";
17914
+ import * as path27 from "path";
17537
17915
 
17538
17916
  // src/commands/agents.ts
17539
17917
  function handleAgentsCommand(agents, guardrails) {
@@ -18253,7 +18631,8 @@ var CuratorConfigSchema = exports_external.object({
18253
18631
  min_knowledge_confidence: exports_external.number().min(0).max(1).default(0.7),
18254
18632
  compliance_report: exports_external.boolean().default(true),
18255
18633
  suppress_warnings: exports_external.boolean().default(true),
18256
- drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500)
18634
+ drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500),
18635
+ llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000)
18257
18636
  });
18258
18637
  var SlopDetectorConfigSchema = exports_external.object({
18259
18638
  enabled: exports_external.boolean().default(true),
@@ -31619,7 +31998,7 @@ async function handleClarifyCommand(_directory, args) {
31619
31998
  }
31620
31999
 
31621
32000
  // src/commands/close.ts
31622
- import { promises as fs4 } from "fs";
32001
+ import { promises as fs6 } from "fs";
31623
32002
  init_manager();
31624
32003
 
31625
32004
  // src/hooks/knowledge-store.ts
@@ -32255,10 +32634,31 @@ async function runAutoPromotion(directory, config3) {
32255
32634
  // src/commands/close.ts
32256
32635
  init_utils2();
32257
32636
 
32637
+ // src/plan/checkpoint.ts
32638
+ init_plan_schema();
32639
+ init_ledger();
32640
+ init_manager2();
32641
+ import * as fs5 from "fs";
32642
+ import * as path9 from "path";
32643
+ async function writeCheckpoint(directory) {
32644
+ try {
32645
+ const plan = await loadPlan(directory);
32646
+ if (!plan)
32647
+ return;
32648
+ const jsonPath = path9.join(directory, "SWARM_PLAN.json");
32649
+ const mdPath = path9.join(directory, "SWARM_PLAN.md");
32650
+ fs5.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
32651
+ const md = derivePlanMarkdown(plan);
32652
+ fs5.writeFileSync(mdPath, md, "utf8");
32653
+ } catch (error93) {
32654
+ console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
32655
+ }
32656
+ }
32657
+
32258
32658
  // src/session/snapshot-writer.ts
32259
32659
  init_utils2();
32260
- import { mkdirSync as mkdirSync3, renameSync as renameSync2 } from "fs";
32261
- import * as path7 from "path";
32660
+ import { mkdirSync as mkdirSync4, renameSync as renameSync4 } from "fs";
32661
+ import * as path10 from "path";
32262
32662
  init_utils();
32263
32663
  var _writeInFlight = Promise.resolve();
32264
32664
  function serializeAgentSession(s) {
@@ -32345,11 +32745,11 @@ async function writeSnapshot(directory, state) {
32345
32745
  }
32346
32746
  const content = JSON.stringify(snapshot, null, 2);
32347
32747
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
32348
- const dir = path7.dirname(resolvedPath);
32349
- mkdirSync3(dir, { recursive: true });
32748
+ const dir = path10.dirname(resolvedPath);
32749
+ mkdirSync4(dir, { recursive: true });
32350
32750
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
32351
32751
  await Bun.write(tempPath, content);
32352
- renameSync2(tempPath, resolvedPath);
32752
+ renameSync4(tempPath, resolvedPath);
32353
32753
  } catch (error93) {
32354
32754
  log("[snapshot-writer] write failed", {
32355
32755
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -32708,7 +33108,7 @@ async function handleCloseCommand(directory, _args) {
32708
33108
  const planPath = validateSwarmPath(directory, "plan.json");
32709
33109
  let planData;
32710
33110
  try {
32711
- const content = await fs4.readFile(planPath, "utf-8");
33111
+ const content = await fs6.readFile(planPath, "utf-8");
32712
33112
  planData = JSON.parse(content);
32713
33113
  } catch (error93) {
32714
33114
  return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
@@ -32775,7 +33175,7 @@ async function handleCloseCommand(directory, _args) {
32775
33175
  }
32776
33176
  }
32777
33177
  try {
32778
- await fs4.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
33178
+ await fs6.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
32779
33179
  } catch (error93) {
32780
33180
  console.warn("[close-command] Failed to write plan.json:", error93);
32781
33181
  }
@@ -32807,7 +33207,7 @@ async function handleCloseCommand(directory, _args) {
32807
33207
  ].join(`
32808
33208
  `);
32809
33209
  try {
32810
- await fs4.writeFile(closeSummaryPath, summaryContent, "utf-8");
33210
+ await fs6.writeFile(closeSummaryPath, summaryContent, "utf-8");
32811
33211
  } catch (error93) {
32812
33212
  console.warn("[close-command] Failed to write close-summary.md:", error93);
32813
33213
  }
@@ -32816,6 +33216,7 @@ async function handleCloseCommand(directory, _args) {
32816
33216
  } catch (error93) {
32817
33217
  console.warn("[close-command] flushPendingSnapshot error:", error93);
32818
33218
  }
33219
+ await writeCheckpoint(directory).catch(() => {});
32819
33220
  swarmState.agentSessions.clear();
32820
33221
  swarmState.delegationChains.clear();
32821
33222
  const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
@@ -32824,14 +33225,14 @@ async function handleCloseCommand(directory, _args) {
32824
33225
 
32825
33226
  // src/commands/config.ts
32826
33227
  import * as os3 from "os";
32827
- import * as path8 from "path";
33228
+ import * as path11 from "path";
32828
33229
  function getUserConfigDir2() {
32829
- return process.env.XDG_CONFIG_HOME || path8.join(os3.homedir(), ".config");
33230
+ return process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config");
32830
33231
  }
32831
33232
  async function handleConfigCommand(directory, _args) {
32832
33233
  const config3 = loadPluginConfig(directory);
32833
- const userConfigPath = path8.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
32834
- const projectConfigPath = path8.join(directory, ".opencode", "opencode-swarm.json");
33234
+ const userConfigPath = path11.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
33235
+ const projectConfigPath = path11.join(directory, ".opencode", "opencode-swarm.json");
32835
33236
  const lines = [
32836
33237
  "## Swarm Configuration",
32837
33238
  "",
@@ -32849,7 +33250,7 @@ async function handleConfigCommand(directory, _args) {
32849
33250
  }
32850
33251
 
32851
33252
  // src/hooks/hive-promoter.ts
32852
- import path9 from "path";
33253
+ import path12 from "path";
32853
33254
 
32854
33255
  // src/background/event-bus.ts
32855
33256
  init_utils();
@@ -32921,6 +33322,7 @@ function getGlobalEventBus() {
32921
33322
  }
32922
33323
 
32923
33324
  // src/hooks/curator.ts
33325
+ init_manager2();
32924
33326
  init_utils2();
32925
33327
 
32926
33328
  // src/hooks/hive-promoter.ts
@@ -33103,7 +33505,7 @@ async function promoteToHive(directory, lesson, category) {
33103
33505
  schema_version: 1,
33104
33506
  created_at: new Date().toISOString(),
33105
33507
  updated_at: new Date().toISOString(),
33106
- source_project: path9.basename(directory) || "unknown",
33508
+ source_project: path12.basename(directory) || "unknown",
33107
33509
  encounter_score: 1
33108
33510
  };
33109
33511
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -33181,13 +33583,13 @@ function formatCurationSummary(summary) {
33181
33583
  }
33182
33584
 
33183
33585
  // src/commands/dark-matter.ts
33184
- import path11 from "path";
33586
+ import path14 from "path";
33185
33587
 
33186
33588
  // src/tools/co-change-analyzer.ts
33187
33589
  import * as child_process from "child_process";
33188
33590
  import { randomUUID } from "crypto";
33189
33591
  import { readdir, readFile as readFile2, stat } from "fs/promises";
33190
- import * as path10 from "path";
33592
+ import * as path13 from "path";
33191
33593
  import { promisify } from "util";
33192
33594
  function getExecFileAsync() {
33193
33595
  return promisify(child_process.execFile);
@@ -33289,7 +33691,7 @@ async function scanSourceFiles(dir) {
33289
33691
  try {
33290
33692
  const entries = await readdir(dir, { withFileTypes: true });
33291
33693
  for (const entry of entries) {
33292
- const fullPath = path10.join(dir, entry.name);
33694
+ const fullPath = path13.join(dir, entry.name);
33293
33695
  if (entry.isDirectory()) {
33294
33696
  if (skipDirs.has(entry.name)) {
33295
33697
  continue;
@@ -33297,7 +33699,7 @@ async function scanSourceFiles(dir) {
33297
33699
  const subFiles = await scanSourceFiles(fullPath);
33298
33700
  results.push(...subFiles);
33299
33701
  } else if (entry.isFile()) {
33300
- const ext = path10.extname(entry.name);
33702
+ const ext = path13.extname(entry.name);
33301
33703
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
33302
33704
  results.push(fullPath);
33303
33705
  }
@@ -33319,8 +33721,8 @@ async function getStaticEdges(directory) {
33319
33721
  continue;
33320
33722
  }
33321
33723
  try {
33322
- const sourceDir = path10.dirname(sourceFile);
33323
- const resolvedPath = path10.resolve(sourceDir, importPath);
33724
+ const sourceDir = path13.dirname(sourceFile);
33725
+ const resolvedPath = path13.resolve(sourceDir, importPath);
33324
33726
  const extensions = [
33325
33727
  "",
33326
33728
  ".ts",
@@ -33345,8 +33747,8 @@ async function getStaticEdges(directory) {
33345
33747
  if (!targetFile) {
33346
33748
  continue;
33347
33749
  }
33348
- const relSource = path10.relative(directory, sourceFile).replace(/\\/g, "/");
33349
- const relTarget = path10.relative(directory, targetFile).replace(/\\/g, "/");
33750
+ const relSource = path13.relative(directory, sourceFile).replace(/\\/g, "/");
33751
+ const relTarget = path13.relative(directory, targetFile).replace(/\\/g, "/");
33350
33752
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
33351
33753
  edges.add(key);
33352
33754
  } catch {}
@@ -33358,7 +33760,7 @@ async function getStaticEdges(directory) {
33358
33760
  function isTestImplementationPair(fileA, fileB) {
33359
33761
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
33360
33762
  const getBaseName = (filePath) => {
33361
- const base = path10.basename(filePath);
33763
+ const base = path13.basename(filePath);
33362
33764
  for (const pattern of testPatterns) {
33363
33765
  if (base.endsWith(pattern)) {
33364
33766
  return base.slice(0, -pattern.length);
@@ -33368,16 +33770,16 @@ function isTestImplementationPair(fileA, fileB) {
33368
33770
  };
33369
33771
  const baseA = getBaseName(fileA);
33370
33772
  const baseB = getBaseName(fileB);
33371
- return baseA === baseB && baseA !== path10.basename(fileA) && baseA !== path10.basename(fileB);
33773
+ return baseA === baseB && baseA !== path13.basename(fileA) && baseA !== path13.basename(fileB);
33372
33774
  }
33373
33775
  function hasSharedPrefix(fileA, fileB) {
33374
- const dirA = path10.dirname(fileA);
33375
- const dirB = path10.dirname(fileB);
33776
+ const dirA = path13.dirname(fileA);
33777
+ const dirB = path13.dirname(fileB);
33376
33778
  if (dirA !== dirB) {
33377
33779
  return false;
33378
33780
  }
33379
- const baseA = path10.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33380
- const baseB = path10.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33781
+ const baseA = path13.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33782
+ const baseB = path13.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33381
33783
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
33382
33784
  return true;
33383
33785
  }
@@ -33431,8 +33833,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
33431
33833
  const entries = [];
33432
33834
  const now = new Date().toISOString();
33433
33835
  for (const pair of pairs.slice(0, 10)) {
33434
- const baseA = path10.basename(pair.fileA);
33435
- const baseB = path10.basename(pair.fileB);
33836
+ const baseA = path13.basename(pair.fileA);
33837
+ const baseB = path13.basename(pair.fileB);
33436
33838
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
33437
33839
  if (lesson.length > 280) {
33438
33840
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -33542,7 +33944,7 @@ async function handleDarkMatterCommand(directory, args) {
33542
33944
  const output = formatDarkMatterOutput(pairs);
33543
33945
  if (pairs.length > 0) {
33544
33946
  try {
33545
- const projectName = path11.basename(path11.resolve(directory));
33947
+ const projectName = path14.basename(path14.resolve(directory));
33546
33948
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
33547
33949
  if (entries.length > 0) {
33548
33950
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -33563,8 +33965,8 @@ async function handleDarkMatterCommand(directory, args) {
33563
33965
 
33564
33966
  // src/services/diagnose-service.ts
33565
33967
  import { execSync } from "child_process";
33566
- import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
33567
- import path13 from "path";
33968
+ import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
33969
+ import path15 from "path";
33568
33970
  import { fileURLToPath } from "url";
33569
33971
  init_manager();
33570
33972
  init_utils2();
@@ -33800,7 +34202,7 @@ async function checkConfigBackups(directory) {
33800
34202
  }
33801
34203
  async function checkGitRepository(directory) {
33802
34204
  try {
33803
- if (!existsSync4(directory) || !statSync3(directory).isDirectory()) {
34205
+ if (!existsSync5(directory) || !statSync3(directory).isDirectory()) {
33804
34206
  return {
33805
34207
  name: "Git Repository",
33806
34208
  status: "\u274C",
@@ -33861,8 +34263,8 @@ async function checkSpecStaleness(directory, plan) {
33861
34263
  };
33862
34264
  }
33863
34265
  async function checkConfigParseability(directory) {
33864
- const configPath = path13.join(directory, ".opencode/opencode-swarm.json");
33865
- if (!existsSync4(configPath)) {
34266
+ const configPath = path15.join(directory, ".opencode/opencode-swarm.json");
34267
+ if (!existsSync5(configPath)) {
33866
34268
  return {
33867
34269
  name: "Config Parseability",
33868
34270
  status: "\u2705",
@@ -33870,7 +34272,7 @@ async function checkConfigParseability(directory) {
33870
34272
  };
33871
34273
  }
33872
34274
  try {
33873
- const content = readFileSync3(configPath, "utf-8");
34275
+ const content = readFileSync5(configPath, "utf-8");
33874
34276
  JSON.parse(content);
33875
34277
  return {
33876
34278
  name: "Config Parseability",
@@ -33908,15 +34310,15 @@ async function checkGrammarWasmFiles() {
33908
34310
  "tree-sitter-ini.wasm",
33909
34311
  "tree-sitter-regex.wasm"
33910
34312
  ];
33911
- const thisDir = path13.dirname(fileURLToPath(import.meta.url));
34313
+ const thisDir = path15.dirname(fileURLToPath(import.meta.url));
33912
34314
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
33913
- const grammarDir = isSource ? path13.join(thisDir, "..", "lang", "grammars") : path13.join(thisDir, "lang", "grammars");
34315
+ const grammarDir = isSource ? path15.join(thisDir, "..", "lang", "grammars") : path15.join(thisDir, "lang", "grammars");
33914
34316
  const missing = [];
33915
- if (!existsSync4(path13.join(grammarDir, "tree-sitter.wasm"))) {
34317
+ if (!existsSync5(path15.join(grammarDir, "tree-sitter.wasm"))) {
33916
34318
  missing.push("tree-sitter.wasm (core runtime)");
33917
34319
  }
33918
34320
  for (const file3 of grammarFiles) {
33919
- if (!existsSync4(path13.join(grammarDir, file3))) {
34321
+ if (!existsSync5(path15.join(grammarDir, file3))) {
33920
34322
  missing.push(file3);
33921
34323
  }
33922
34324
  }
@@ -33934,8 +34336,8 @@ async function checkGrammarWasmFiles() {
33934
34336
  };
33935
34337
  }
33936
34338
  async function checkCheckpointManifest(directory) {
33937
- const manifestPath = path13.join(directory, ".swarm/checkpoints.json");
33938
- if (!existsSync4(manifestPath)) {
34339
+ const manifestPath = path15.join(directory, ".swarm/checkpoints.json");
34340
+ if (!existsSync5(manifestPath)) {
33939
34341
  return {
33940
34342
  name: "Checkpoint Manifest",
33941
34343
  status: "\u2705",
@@ -33943,7 +34345,7 @@ async function checkCheckpointManifest(directory) {
33943
34345
  };
33944
34346
  }
33945
34347
  try {
33946
- const content = readFileSync3(manifestPath, "utf-8");
34348
+ const content = readFileSync5(manifestPath, "utf-8");
33947
34349
  const parsed = JSON.parse(content);
33948
34350
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
33949
34351
  return {
@@ -33986,8 +34388,8 @@ async function checkCheckpointManifest(directory) {
33986
34388
  }
33987
34389
  }
33988
34390
  async function checkEventStreamIntegrity(directory) {
33989
- const eventsPath = path13.join(directory, ".swarm/events.jsonl");
33990
- if (!existsSync4(eventsPath)) {
34391
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34392
+ if (!existsSync5(eventsPath)) {
33991
34393
  return {
33992
34394
  name: "Event Stream",
33993
34395
  status: "\u2705",
@@ -33995,7 +34397,7 @@ async function checkEventStreamIntegrity(directory) {
33995
34397
  };
33996
34398
  }
33997
34399
  try {
33998
- const content = readFileSync3(eventsPath, "utf-8");
34400
+ const content = readFileSync5(eventsPath, "utf-8");
33999
34401
  const lines = content.split(`
34000
34402
  `).filter((line) => line.trim() !== "");
34001
34403
  let malformedCount = 0;
@@ -34027,8 +34429,8 @@ async function checkEventStreamIntegrity(directory) {
34027
34429
  }
34028
34430
  }
34029
34431
  async function checkSteeringDirectives(directory) {
34030
- const eventsPath = path13.join(directory, ".swarm/events.jsonl");
34031
- if (!existsSync4(eventsPath)) {
34432
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34433
+ if (!existsSync5(eventsPath)) {
34032
34434
  return {
34033
34435
  name: "Steering Directives",
34034
34436
  status: "\u2705",
@@ -34036,7 +34438,7 @@ async function checkSteeringDirectives(directory) {
34036
34438
  };
34037
34439
  }
34038
34440
  try {
34039
- const content = readFileSync3(eventsPath, "utf-8");
34441
+ const content = readFileSync5(eventsPath, "utf-8");
34040
34442
  const lines = content.split(`
34041
34443
  `).filter((line) => line.trim() !== "");
34042
34444
  const directivesIssued = [];
@@ -34083,8 +34485,8 @@ async function checkCurator(directory) {
34083
34485
  detail: "Disabled (enable via curator.enabled)"
34084
34486
  };
34085
34487
  }
34086
- const summaryPath = path13.join(directory, ".swarm/curator-summary.json");
34087
- if (!existsSync4(summaryPath)) {
34488
+ const summaryPath = path15.join(directory, ".swarm/curator-summary.json");
34489
+ if (!existsSync5(summaryPath)) {
34088
34490
  return {
34089
34491
  name: "Curator",
34090
34492
  status: "\u2705",
@@ -34092,7 +34494,7 @@ async function checkCurator(directory) {
34092
34494
  };
34093
34495
  }
34094
34496
  try {
34095
- const content = readFileSync3(summaryPath, "utf-8");
34497
+ const content = readFileSync5(summaryPath, "utf-8");
34096
34498
  const parsed = JSON.parse(content);
34097
34499
  if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
34098
34500
  return {
@@ -34522,8 +34924,8 @@ async function handleExportCommand(directory, _args) {
34522
34924
  }
34523
34925
  // src/commands/handoff.ts
34524
34926
  init_utils2();
34525
- import crypto3 from "crypto";
34526
- import { renameSync as renameSync4 } from "fs";
34927
+ import crypto4 from "crypto";
34928
+ import { renameSync as renameSync5 } from "fs";
34527
34929
 
34528
34930
  // src/services/handoff-service.ts
34529
34931
  init_utils2();
@@ -34831,9 +35233,9 @@ async function handleHandoffCommand(directory, _args) {
34831
35233
  const handoffData = await getHandoffData(directory);
34832
35234
  const markdown = formatHandoffMarkdown(handoffData);
34833
35235
  const resolvedPath = validateSwarmPath(directory, "handoff.md");
34834
- const tempPath = `${resolvedPath}.tmp.${crypto3.randomUUID()}`;
35236
+ const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
34835
35237
  await Bun.write(tempPath, markdown);
34836
- renameSync4(tempPath, resolvedPath);
35238
+ renameSync5(tempPath, resolvedPath);
34837
35239
  await writeSnapshot(directory, swarmState);
34838
35240
  await flushPendingSnapshot(directory);
34839
35241
  return `## Handoff Brief Written
@@ -34978,14 +35380,14 @@ async function handleHistoryCommand(directory, _args) {
34978
35380
  }
34979
35381
  // src/hooks/knowledge-migrator.ts
34980
35382
  import { randomUUID as randomUUID2 } from "crypto";
34981
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
35383
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
34982
35384
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
34983
- import * as path15 from "path";
35385
+ import * as path17 from "path";
34984
35386
  async function migrateContextToKnowledge(directory, config3) {
34985
- const sentinelPath = path15.join(directory, ".swarm", ".knowledge-migrated");
34986
- const contextPath = path15.join(directory, ".swarm", "context.md");
35387
+ const sentinelPath = path17.join(directory, ".swarm", ".knowledge-migrated");
35388
+ const contextPath = path17.join(directory, ".swarm", "context.md");
34987
35389
  const knowledgePath = resolveSwarmKnowledgePath(directory);
34988
- if (existsSync6(sentinelPath)) {
35390
+ if (existsSync7(sentinelPath)) {
34989
35391
  return {
34990
35392
  migrated: false,
34991
35393
  entriesMigrated: 0,
@@ -34994,7 +35396,7 @@ async function migrateContextToKnowledge(directory, config3) {
34994
35396
  skippedReason: "sentinel-exists"
34995
35397
  };
34996
35398
  }
34997
- if (!existsSync6(contextPath)) {
35399
+ if (!existsSync7(contextPath)) {
34998
35400
  return {
34999
35401
  migrated: false,
35000
35402
  entriesMigrated: 0,
@@ -35179,16 +35581,16 @@ function truncateLesson(text) {
35179
35581
  return `${text.slice(0, 277)}...`;
35180
35582
  }
35181
35583
  function inferProjectName(directory) {
35182
- const packageJsonPath = path15.join(directory, "package.json");
35183
- if (existsSync6(packageJsonPath)) {
35584
+ const packageJsonPath = path17.join(directory, "package.json");
35585
+ if (existsSync7(packageJsonPath)) {
35184
35586
  try {
35185
- const pkg = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
35587
+ const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
35186
35588
  if (pkg.name && typeof pkg.name === "string") {
35187
35589
  return pkg.name;
35188
35590
  }
35189
35591
  } catch {}
35190
35592
  }
35191
- return path15.basename(directory);
35593
+ return path17.basename(directory);
35192
35594
  }
35193
35595
  async function writeSentinel(sentinelPath, migrated, dropped) {
35194
35596
  const sentinel = {
@@ -35200,7 +35602,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
35200
35602
  schema_version: 1,
35201
35603
  migration_tool: "knowledge-migrator.ts"
35202
35604
  };
35203
- await mkdir3(path15.dirname(sentinelPath), { recursive: true });
35605
+ await mkdir3(path17.dirname(sentinelPath), { recursive: true });
35204
35606
  await writeFile3(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
35205
35607
  }
35206
35608
 
@@ -35436,20 +35838,20 @@ async function handlePlanCommand(directory, args) {
35436
35838
  // src/services/preflight-service.ts
35437
35839
  init_manager();
35438
35840
  init_manager2();
35439
- import * as fs11 from "fs";
35440
- import * as path21 from "path";
35841
+ import * as fs13 from "fs";
35842
+ import * as path23 from "path";
35441
35843
 
35442
35844
  // src/tools/lint.ts
35443
- import * as fs7 from "fs";
35444
- import * as path17 from "path";
35845
+ import * as fs9 from "fs";
35846
+ import * as path19 from "path";
35445
35847
 
35446
35848
  // src/build/discovery.ts
35447
- import * as fs6 from "fs";
35448
- import * as path16 from "path";
35849
+ import * as fs8 from "fs";
35850
+ import * as path18 from "path";
35449
35851
 
35450
35852
  // src/lang/detector.ts
35451
35853
  import { access, readdir as readdir2 } from "fs/promises";
35452
- import { extname as extname2, join as join11 } from "path";
35854
+ import { extname as extname2, join as join13 } from "path";
35453
35855
 
35454
35856
  // src/lang/profiles.ts
35455
35857
  class LanguageRegistry {
@@ -36374,7 +36776,7 @@ async function detectProjectLanguages(projectDir) {
36374
36776
  if (detectFile.includes("*") || detectFile.includes("?"))
36375
36777
  continue;
36376
36778
  try {
36377
- await access(join11(dir, detectFile));
36779
+ await access(join13(dir, detectFile));
36378
36780
  detected.add(profile.id);
36379
36781
  break;
36380
36782
  } catch {}
@@ -36395,7 +36797,7 @@ async function detectProjectLanguages(projectDir) {
36395
36797
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
36396
36798
  for (const entry of topEntries) {
36397
36799
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
36398
- await scanDir(join11(projectDir, entry.name));
36800
+ await scanDir(join13(projectDir, entry.name));
36399
36801
  }
36400
36802
  }
36401
36803
  } catch {}
@@ -36538,16 +36940,16 @@ function findBuildFiles(workingDir, patterns) {
36538
36940
  if (pattern.includes("*")) {
36539
36941
  const dir = workingDir;
36540
36942
  try {
36541
- const files = fs6.readdirSync(dir);
36943
+ const files = fs8.readdirSync(dir);
36542
36944
  const regex = simpleGlobToRegex(pattern);
36543
36945
  const matches = files.filter((f) => regex.test(f));
36544
36946
  if (matches.length > 0) {
36545
- return path16.join(dir, matches[0]);
36947
+ return path18.join(dir, matches[0]);
36546
36948
  }
36547
36949
  } catch {}
36548
36950
  } else {
36549
- const filePath = path16.join(workingDir, pattern);
36550
- if (fs6.existsSync(filePath)) {
36951
+ const filePath = path18.join(workingDir, pattern);
36952
+ if (fs8.existsSync(filePath)) {
36551
36953
  return filePath;
36552
36954
  }
36553
36955
  }
@@ -36555,12 +36957,12 @@ function findBuildFiles(workingDir, patterns) {
36555
36957
  return null;
36556
36958
  }
36557
36959
  function getRepoDefinedScripts(workingDir, scripts) {
36558
- const packageJsonPath = path16.join(workingDir, "package.json");
36559
- if (!fs6.existsSync(packageJsonPath)) {
36960
+ const packageJsonPath = path18.join(workingDir, "package.json");
36961
+ if (!fs8.existsSync(packageJsonPath)) {
36560
36962
  return [];
36561
36963
  }
36562
36964
  try {
36563
- const content = fs6.readFileSync(packageJsonPath, "utf-8");
36965
+ const content = fs8.readFileSync(packageJsonPath, "utf-8");
36564
36966
  const pkg = JSON.parse(content);
36565
36967
  if (!pkg.scripts || typeof pkg.scripts !== "object") {
36566
36968
  return [];
@@ -36596,8 +36998,8 @@ function findAllBuildFiles(workingDir) {
36596
36998
  const regex = simpleGlobToRegex(pattern);
36597
36999
  findFilesRecursive(workingDir, regex, allBuildFiles);
36598
37000
  } else {
36599
- const filePath = path16.join(workingDir, pattern);
36600
- if (fs6.existsSync(filePath)) {
37001
+ const filePath = path18.join(workingDir, pattern);
37002
+ if (fs8.existsSync(filePath)) {
36601
37003
  allBuildFiles.add(filePath);
36602
37004
  }
36603
37005
  }
@@ -36607,9 +37009,9 @@ function findAllBuildFiles(workingDir) {
36607
37009
  }
36608
37010
  function findFilesRecursive(dir, regex, results) {
36609
37011
  try {
36610
- const entries = fs6.readdirSync(dir, { withFileTypes: true });
37012
+ const entries = fs8.readdirSync(dir, { withFileTypes: true });
36611
37013
  for (const entry of entries) {
36612
- const fullPath = path16.join(dir, entry.name);
37014
+ const fullPath = path18.join(dir, entry.name);
36613
37015
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
36614
37016
  findFilesRecursive(fullPath, regex, results);
36615
37017
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -36632,8 +37034,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
36632
37034
  let foundCommand = false;
36633
37035
  for (const cmd of sortedCommands) {
36634
37036
  if (cmd.detectFile) {
36635
- const detectFilePath = path16.join(workingDir, cmd.detectFile);
36636
- if (!fs6.existsSync(detectFilePath)) {
37037
+ const detectFilePath = path18.join(workingDir, cmd.detectFile);
37038
+ if (!fs8.existsSync(detectFilePath)) {
36637
37039
  continue;
36638
37040
  }
36639
37041
  }
@@ -36780,9 +37182,9 @@ function validateArgs(args) {
36780
37182
  }
36781
37183
  function getLinterCommand(linter, mode, projectDir) {
36782
37184
  const isWindows = process.platform === "win32";
36783
- const binDir = path17.join(projectDir, "node_modules", ".bin");
36784
- const biomeBin = isWindows ? path17.join(binDir, "biome.EXE") : path17.join(binDir, "biome");
36785
- const eslintBin = isWindows ? path17.join(binDir, "eslint.cmd") : path17.join(binDir, "eslint");
37185
+ const binDir = path19.join(projectDir, "node_modules", ".bin");
37186
+ const biomeBin = isWindows ? path19.join(binDir, "biome.EXE") : path19.join(binDir, "biome");
37187
+ const eslintBin = isWindows ? path19.join(binDir, "eslint.cmd") : path19.join(binDir, "eslint");
36786
37188
  switch (linter) {
36787
37189
  case "biome":
36788
37190
  if (mode === "fix") {
@@ -36798,7 +37200,7 @@ function getLinterCommand(linter, mode, projectDir) {
36798
37200
  }
36799
37201
  function getAdditionalLinterCommand(linter, mode, cwd) {
36800
37202
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
36801
- const gradlew = fs7.existsSync(path17.join(cwd, gradlewName)) ? path17.join(cwd, gradlewName) : null;
37203
+ const gradlew = fs9.existsSync(path19.join(cwd, gradlewName)) ? path19.join(cwd, gradlewName) : null;
36802
37204
  switch (linter) {
36803
37205
  case "ruff":
36804
37206
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -36832,12 +37234,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
36832
37234
  }
36833
37235
  }
36834
37236
  function detectRuff(cwd) {
36835
- if (fs7.existsSync(path17.join(cwd, "ruff.toml")))
37237
+ if (fs9.existsSync(path19.join(cwd, "ruff.toml")))
36836
37238
  return isCommandAvailable("ruff");
36837
37239
  try {
36838
- const pyproject = path17.join(cwd, "pyproject.toml");
36839
- if (fs7.existsSync(pyproject)) {
36840
- const content = fs7.readFileSync(pyproject, "utf-8");
37240
+ const pyproject = path19.join(cwd, "pyproject.toml");
37241
+ if (fs9.existsSync(pyproject)) {
37242
+ const content = fs9.readFileSync(pyproject, "utf-8");
36841
37243
  if (content.includes("[tool.ruff]"))
36842
37244
  return isCommandAvailable("ruff");
36843
37245
  }
@@ -36845,21 +37247,21 @@ function detectRuff(cwd) {
36845
37247
  return false;
36846
37248
  }
36847
37249
  function detectClippy(cwd) {
36848
- return fs7.existsSync(path17.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37250
+ return fs9.existsSync(path19.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
36849
37251
  }
36850
37252
  function detectGolangciLint(cwd) {
36851
- return fs7.existsSync(path17.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37253
+ return fs9.existsSync(path19.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
36852
37254
  }
36853
37255
  function detectCheckstyle(cwd) {
36854
- const hasMaven = fs7.existsSync(path17.join(cwd, "pom.xml"));
36855
- const hasGradle = fs7.existsSync(path17.join(cwd, "build.gradle")) || fs7.existsSync(path17.join(cwd, "build.gradle.kts"));
36856
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs7.existsSync(path17.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
37256
+ const hasMaven = fs9.existsSync(path19.join(cwd, "pom.xml"));
37257
+ const hasGradle = fs9.existsSync(path19.join(cwd, "build.gradle")) || fs9.existsSync(path19.join(cwd, "build.gradle.kts"));
37258
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs9.existsSync(path19.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
36857
37259
  return (hasMaven || hasGradle) && hasBinary;
36858
37260
  }
36859
37261
  function detectKtlint(cwd) {
36860
- const hasKotlin = fs7.existsSync(path17.join(cwd, "build.gradle.kts")) || fs7.existsSync(path17.join(cwd, "build.gradle")) || (() => {
37262
+ const hasKotlin = fs9.existsSync(path19.join(cwd, "build.gradle.kts")) || fs9.existsSync(path19.join(cwd, "build.gradle")) || (() => {
36861
37263
  try {
36862
- return fs7.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
37264
+ return fs9.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
36863
37265
  } catch {
36864
37266
  return false;
36865
37267
  }
@@ -36868,7 +37270,7 @@ function detectKtlint(cwd) {
36868
37270
  }
36869
37271
  function detectDotnetFormat(cwd) {
36870
37272
  try {
36871
- const files = fs7.readdirSync(cwd);
37273
+ const files = fs9.readdirSync(cwd);
36872
37274
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
36873
37275
  return hasCsproj && isCommandAvailable("dotnet");
36874
37276
  } catch {
@@ -36876,14 +37278,14 @@ function detectDotnetFormat(cwd) {
36876
37278
  }
36877
37279
  }
36878
37280
  function detectCppcheck(cwd) {
36879
- if (fs7.existsSync(path17.join(cwd, "CMakeLists.txt"))) {
37281
+ if (fs9.existsSync(path19.join(cwd, "CMakeLists.txt"))) {
36880
37282
  return isCommandAvailable("cppcheck");
36881
37283
  }
36882
37284
  try {
36883
- const dirsToCheck = [cwd, path17.join(cwd, "src")];
37285
+ const dirsToCheck = [cwd, path19.join(cwd, "src")];
36884
37286
  const hasCpp = dirsToCheck.some((dir) => {
36885
37287
  try {
36886
- return fs7.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
37288
+ return fs9.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
36887
37289
  } catch {
36888
37290
  return false;
36889
37291
  }
@@ -36894,13 +37296,13 @@ function detectCppcheck(cwd) {
36894
37296
  }
36895
37297
  }
36896
37298
  function detectSwiftlint(cwd) {
36897
- return fs7.existsSync(path17.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37299
+ return fs9.existsSync(path19.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
36898
37300
  }
36899
37301
  function detectDartAnalyze(cwd) {
36900
- return fs7.existsSync(path17.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37302
+ return fs9.existsSync(path19.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
36901
37303
  }
36902
37304
  function detectRubocop(cwd) {
36903
- return (fs7.existsSync(path17.join(cwd, "Gemfile")) || fs7.existsSync(path17.join(cwd, "gems.rb")) || fs7.existsSync(path17.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
37305
+ return (fs9.existsSync(path19.join(cwd, "Gemfile")) || fs9.existsSync(path19.join(cwd, "gems.rb")) || fs9.existsSync(path19.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
36904
37306
  }
36905
37307
  function detectAdditionalLinter(cwd) {
36906
37308
  if (detectRuff(cwd))
@@ -36929,12 +37331,12 @@ async function detectAvailableLinter(directory) {
36929
37331
  const _DETECT_TIMEOUT = 2000;
36930
37332
  if (!directory)
36931
37333
  return null;
36932
- if (!fs7.existsSync(directory))
37334
+ if (!fs9.existsSync(directory))
36933
37335
  return null;
36934
37336
  const projectDir = directory;
36935
37337
  const isWindows = process.platform === "win32";
36936
- const biomeBin = isWindows ? path17.join(projectDir, "node_modules", ".bin", "biome.EXE") : path17.join(projectDir, "node_modules", ".bin", "biome");
36937
- const eslintBin = isWindows ? path17.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path17.join(projectDir, "node_modules", ".bin", "eslint");
37338
+ const biomeBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "biome.EXE") : path19.join(projectDir, "node_modules", ".bin", "biome");
37339
+ const eslintBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path19.join(projectDir, "node_modules", ".bin", "eslint");
36938
37340
  return _detectAvailableLinter(projectDir, biomeBin, eslintBin);
36939
37341
  }
36940
37342
  async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
@@ -36949,7 +37351,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36949
37351
  const result = await Promise.race([biomeExit, timeout]);
36950
37352
  if (result === "timeout") {
36951
37353
  biomeProc.kill();
36952
- } else if (biomeProc.exitCode === 0 && fs7.existsSync(biomeBin)) {
37354
+ } else if (biomeProc.exitCode === 0 && fs9.existsSync(biomeBin)) {
36953
37355
  return "biome";
36954
37356
  }
36955
37357
  } catch {}
@@ -36963,7 +37365,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36963
37365
  const result = await Promise.race([eslintExit, timeout]);
36964
37366
  if (result === "timeout") {
36965
37367
  eslintProc.kill();
36966
- } else if (eslintProc.exitCode === 0 && fs7.existsSync(eslintBin)) {
37368
+ } else if (eslintProc.exitCode === 0 && fs9.existsSync(eslintBin)) {
36967
37369
  return "eslint";
36968
37370
  }
36969
37371
  } catch {}
@@ -37133,8 +37535,8 @@ For Rust: rustup component add clippy`
37133
37535
  });
37134
37536
 
37135
37537
  // src/tools/secretscan.ts
37136
- import * as fs8 from "fs";
37137
- import * as path18 from "path";
37538
+ import * as fs10 from "fs";
37539
+ import * as path20 from "path";
37138
37540
  var MAX_FILE_PATH_LENGTH = 500;
37139
37541
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
37140
37542
  var MAX_FILES_SCANNED = 1000;
@@ -37361,11 +37763,11 @@ function isGlobOrPathPattern(pattern) {
37361
37763
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
37362
37764
  }
37363
37765
  function loadSecretScanIgnore(scanDir) {
37364
- const ignorePath = path18.join(scanDir, ".secretscanignore");
37766
+ const ignorePath = path20.join(scanDir, ".secretscanignore");
37365
37767
  try {
37366
- if (!fs8.existsSync(ignorePath))
37768
+ if (!fs10.existsSync(ignorePath))
37367
37769
  return [];
37368
- const content = fs8.readFileSync(ignorePath, "utf8");
37770
+ const content = fs10.readFileSync(ignorePath, "utf8");
37369
37771
  const patterns = [];
37370
37772
  for (const rawLine of content.split(/\r?\n/)) {
37371
37773
  const line = rawLine.trim();
@@ -37384,7 +37786,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
37384
37786
  if (exactNames.has(entry))
37385
37787
  return true;
37386
37788
  for (const pattern of globPatterns) {
37387
- if (path18.matchesGlob(relPath, pattern))
37789
+ if (path20.matchesGlob(relPath, pattern))
37388
37790
  return true;
37389
37791
  }
37390
37792
  return false;
@@ -37405,7 +37807,7 @@ function validateDirectoryInput(dir) {
37405
37807
  return null;
37406
37808
  }
37407
37809
  function isBinaryFile(filePath, buffer) {
37408
- const ext = path18.extname(filePath).toLowerCase();
37810
+ const ext = path20.extname(filePath).toLowerCase();
37409
37811
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37410
37812
  return true;
37411
37813
  }
@@ -37480,11 +37882,11 @@ function createRedactedContext(line, findings) {
37480
37882
  result += line.slice(lastEnd);
37481
37883
  return result;
37482
37884
  }
37483
- var O_NOFOLLOW = process.platform !== "win32" ? fs8.constants.O_NOFOLLOW : undefined;
37885
+ var O_NOFOLLOW = process.platform !== "win32" ? fs10.constants.O_NOFOLLOW : undefined;
37484
37886
  function scanFileForSecrets(filePath) {
37485
37887
  const findings = [];
37486
37888
  try {
37487
- const lstat = fs8.lstatSync(filePath);
37889
+ const lstat = fs10.lstatSync(filePath);
37488
37890
  if (lstat.isSymbolicLink()) {
37489
37891
  return findings;
37490
37892
  }
@@ -37493,14 +37895,14 @@ function scanFileForSecrets(filePath) {
37493
37895
  }
37494
37896
  let buffer;
37495
37897
  if (O_NOFOLLOW !== undefined) {
37496
- const fd = fs8.openSync(filePath, "r", O_NOFOLLOW);
37898
+ const fd = fs10.openSync(filePath, "r", O_NOFOLLOW);
37497
37899
  try {
37498
- buffer = fs8.readFileSync(fd);
37900
+ buffer = fs10.readFileSync(fd);
37499
37901
  } finally {
37500
- fs8.closeSync(fd);
37902
+ fs10.closeSync(fd);
37501
37903
  }
37502
37904
  } else {
37503
- buffer = fs8.readFileSync(filePath);
37905
+ buffer = fs10.readFileSync(filePath);
37504
37906
  }
37505
37907
  if (isBinaryFile(filePath, buffer)) {
37506
37908
  return findings;
@@ -37542,9 +37944,9 @@ function isSymlinkLoop(realPath, visited) {
37542
37944
  return false;
37543
37945
  }
37544
37946
  function isPathWithinScope(realPath, scanDir) {
37545
- const resolvedScanDir = path18.resolve(scanDir);
37546
- const resolvedRealPath = path18.resolve(realPath);
37547
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path18.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
37947
+ const resolvedScanDir = path20.resolve(scanDir);
37948
+ const resolvedRealPath = path20.resolve(realPath);
37949
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path20.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
37548
37950
  }
37549
37951
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
37550
37952
  skippedDirs: 0,
@@ -37555,7 +37957,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37555
37957
  const files = [];
37556
37958
  let entries;
37557
37959
  try {
37558
- entries = fs8.readdirSync(dir);
37960
+ entries = fs10.readdirSync(dir);
37559
37961
  } catch {
37560
37962
  stats.fileErrors++;
37561
37963
  return files;
@@ -37570,15 +37972,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37570
37972
  return a.localeCompare(b);
37571
37973
  });
37572
37974
  for (const entry of entries) {
37573
- const fullPath = path18.join(dir, entry);
37574
- const relPath = path18.relative(scanDir, fullPath).replace(/\\/g, "/");
37975
+ const fullPath = path20.join(dir, entry);
37976
+ const relPath = path20.relative(scanDir, fullPath).replace(/\\/g, "/");
37575
37977
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
37576
37978
  stats.skippedDirs++;
37577
37979
  continue;
37578
37980
  }
37579
37981
  let lstat;
37580
37982
  try {
37581
- lstat = fs8.lstatSync(fullPath);
37983
+ lstat = fs10.lstatSync(fullPath);
37582
37984
  } catch {
37583
37985
  stats.fileErrors++;
37584
37986
  continue;
@@ -37590,7 +37992,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37590
37992
  if (lstat.isDirectory()) {
37591
37993
  let realPath;
37592
37994
  try {
37593
- realPath = fs8.realpathSync(fullPath);
37995
+ realPath = fs10.realpathSync(fullPath);
37594
37996
  } catch {
37595
37997
  stats.fileErrors++;
37596
37998
  continue;
@@ -37606,7 +38008,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37606
38008
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
37607
38009
  files.push(...subFiles);
37608
38010
  } else if (lstat.isFile()) {
37609
- const ext = path18.extname(fullPath).toLowerCase();
38011
+ const ext = path20.extname(fullPath).toLowerCase();
37610
38012
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37611
38013
  files.push(fullPath);
37612
38014
  } else {
@@ -37672,8 +38074,8 @@ var secretscan = createSwarmTool({
37672
38074
  }
37673
38075
  }
37674
38076
  try {
37675
- const scanDir = path18.resolve(directory);
37676
- if (!fs8.existsSync(scanDir)) {
38077
+ const scanDir = path20.resolve(directory);
38078
+ if (!fs10.existsSync(scanDir)) {
37677
38079
  const errorResult = {
37678
38080
  error: "directory not found",
37679
38081
  scan_dir: directory,
@@ -37684,7 +38086,7 @@ var secretscan = createSwarmTool({
37684
38086
  };
37685
38087
  return JSON.stringify(errorResult, null, 2);
37686
38088
  }
37687
- const dirStat = fs8.statSync(scanDir);
38089
+ const dirStat = fs10.statSync(scanDir);
37688
38090
  if (!dirStat.isDirectory()) {
37689
38091
  const errorResult = {
37690
38092
  error: "target must be a directory, not a file",
@@ -37735,7 +38137,7 @@ var secretscan = createSwarmTool({
37735
38137
  break;
37736
38138
  const fileFindings = scanFileForSecrets(filePath);
37737
38139
  try {
37738
- const stat2 = fs8.statSync(filePath);
38140
+ const stat2 = fs10.statSync(filePath);
37739
38141
  if (stat2.size > MAX_FILE_SIZE_BYTES) {
37740
38142
  skippedFiles++;
37741
38143
  continue;
@@ -37822,12 +38224,12 @@ async function runSecretscan(directory) {
37822
38224
  }
37823
38225
 
37824
38226
  // src/tools/test-runner.ts
37825
- import * as fs10 from "fs";
37826
- import * as path20 from "path";
38227
+ import * as fs12 from "fs";
38228
+ import * as path22 from "path";
37827
38229
 
37828
38230
  // src/tools/resolve-working-directory.ts
37829
- import * as fs9 from "fs";
37830
- import * as path19 from "path";
38231
+ import * as fs11 from "fs";
38232
+ import * as path21 from "path";
37831
38233
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
37832
38234
  if (workingDirectory == null || workingDirectory === "") {
37833
38235
  return { success: true, directory: fallbackDirectory };
@@ -37847,17 +38249,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
37847
38249
  };
37848
38250
  }
37849
38251
  }
37850
- const normalizedDir = path19.normalize(workingDirectory);
37851
- const pathParts = normalizedDir.split(path19.sep);
38252
+ const normalizedDir = path21.normalize(workingDirectory);
38253
+ const pathParts = normalizedDir.split(path21.sep);
37852
38254
  if (pathParts.includes("..")) {
37853
38255
  return {
37854
38256
  success: false,
37855
38257
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
37856
38258
  };
37857
38259
  }
37858
- const resolvedDir = path19.resolve(normalizedDir);
38260
+ const resolvedDir = path21.resolve(normalizedDir);
37859
38261
  try {
37860
- const realPath = fs9.realpathSync(resolvedDir);
38262
+ const realPath = fs11.realpathSync(resolvedDir);
37861
38263
  return { success: true, directory: realPath };
37862
38264
  } catch {
37863
38265
  return {
@@ -37938,19 +38340,19 @@ function hasDevDependency(devDeps, ...patterns) {
37938
38340
  return hasPackageJsonDependency(devDeps, ...patterns);
37939
38341
  }
37940
38342
  function detectGoTest(cwd) {
37941
- return fs10.existsSync(path20.join(cwd, "go.mod")) && isCommandAvailable("go");
38343
+ return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("go");
37942
38344
  }
37943
38345
  function detectJavaMaven(cwd) {
37944
- return fs10.existsSync(path20.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38346
+ return fs12.existsSync(path22.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
37945
38347
  }
37946
38348
  function detectGradle(cwd) {
37947
- const hasBuildFile = fs10.existsSync(path20.join(cwd, "build.gradle")) || fs10.existsSync(path20.join(cwd, "build.gradle.kts"));
37948
- const hasGradlew = fs10.existsSync(path20.join(cwd, "gradlew")) || fs10.existsSync(path20.join(cwd, "gradlew.bat"));
38349
+ const hasBuildFile = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
38350
+ const hasGradlew = fs12.existsSync(path22.join(cwd, "gradlew")) || fs12.existsSync(path22.join(cwd, "gradlew.bat"));
37949
38351
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
37950
38352
  }
37951
38353
  function detectDotnetTest(cwd) {
37952
38354
  try {
37953
- const files = fs10.readdirSync(cwd);
38355
+ const files = fs12.readdirSync(cwd);
37954
38356
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
37955
38357
  return hasCsproj && isCommandAvailable("dotnet");
37956
38358
  } catch {
@@ -37958,32 +38360,32 @@ function detectDotnetTest(cwd) {
37958
38360
  }
37959
38361
  }
37960
38362
  function detectCTest(cwd) {
37961
- const hasSource = fs10.existsSync(path20.join(cwd, "CMakeLists.txt"));
37962
- const hasBuildCache = fs10.existsSync(path20.join(cwd, "CMakeCache.txt")) || fs10.existsSync(path20.join(cwd, "build", "CMakeCache.txt"));
38363
+ const hasSource = fs12.existsSync(path22.join(cwd, "CMakeLists.txt"));
38364
+ const hasBuildCache = fs12.existsSync(path22.join(cwd, "CMakeCache.txt")) || fs12.existsSync(path22.join(cwd, "build", "CMakeCache.txt"));
37963
38365
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
37964
38366
  }
37965
38367
  function detectSwiftTest(cwd) {
37966
- return fs10.existsSync(path20.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38368
+ return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swift");
37967
38369
  }
37968
38370
  function detectDartTest(cwd) {
37969
- return fs10.existsSync(path20.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
38371
+ return fs12.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37970
38372
  }
37971
38373
  function detectRSpec(cwd) {
37972
- const hasRSpecFile = fs10.existsSync(path20.join(cwd, ".rspec"));
37973
- const hasGemfile = fs10.existsSync(path20.join(cwd, "Gemfile"));
37974
- const hasSpecDir = fs10.existsSync(path20.join(cwd, "spec"));
38374
+ const hasRSpecFile = fs12.existsSync(path22.join(cwd, ".rspec"));
38375
+ const hasGemfile = fs12.existsSync(path22.join(cwd, "Gemfile"));
38376
+ const hasSpecDir = fs12.existsSync(path22.join(cwd, "spec"));
37975
38377
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
37976
38378
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
37977
38379
  }
37978
38380
  function detectMinitest(cwd) {
37979
- return fs10.existsSync(path20.join(cwd, "test")) && (fs10.existsSync(path20.join(cwd, "Gemfile")) || fs10.existsSync(path20.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
38381
+ return fs12.existsSync(path22.join(cwd, "test")) && (fs12.existsSync(path22.join(cwd, "Gemfile")) || fs12.existsSync(path22.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
37980
38382
  }
37981
38383
  async function detectTestFramework(cwd) {
37982
38384
  const baseDir = cwd;
37983
38385
  try {
37984
- const packageJsonPath = path20.join(baseDir, "package.json");
37985
- if (fs10.existsSync(packageJsonPath)) {
37986
- const content = fs10.readFileSync(packageJsonPath, "utf-8");
38386
+ const packageJsonPath = path22.join(baseDir, "package.json");
38387
+ if (fs12.existsSync(packageJsonPath)) {
38388
+ const content = fs12.readFileSync(packageJsonPath, "utf-8");
37987
38389
  const pkg = JSON.parse(content);
37988
38390
  const _deps = pkg.dependencies || {};
37989
38391
  const devDeps = pkg.devDependencies || {};
@@ -38002,38 +38404,38 @@ async function detectTestFramework(cwd) {
38002
38404
  return "jest";
38003
38405
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
38004
38406
  return "mocha";
38005
- if (fs10.existsSync(path20.join(baseDir, "bun.lockb")) || fs10.existsSync(path20.join(baseDir, "bun.lock"))) {
38407
+ if (fs12.existsSync(path22.join(baseDir, "bun.lockb")) || fs12.existsSync(path22.join(baseDir, "bun.lock"))) {
38006
38408
  if (scripts.test?.includes("bun"))
38007
38409
  return "bun";
38008
38410
  }
38009
38411
  }
38010
38412
  } catch {}
38011
38413
  try {
38012
- const pyprojectTomlPath = path20.join(baseDir, "pyproject.toml");
38013
- const setupCfgPath = path20.join(baseDir, "setup.cfg");
38014
- const requirementsTxtPath = path20.join(baseDir, "requirements.txt");
38015
- if (fs10.existsSync(pyprojectTomlPath)) {
38016
- const content = fs10.readFileSync(pyprojectTomlPath, "utf-8");
38414
+ const pyprojectTomlPath = path22.join(baseDir, "pyproject.toml");
38415
+ const setupCfgPath = path22.join(baseDir, "setup.cfg");
38416
+ const requirementsTxtPath = path22.join(baseDir, "requirements.txt");
38417
+ if (fs12.existsSync(pyprojectTomlPath)) {
38418
+ const content = fs12.readFileSync(pyprojectTomlPath, "utf-8");
38017
38419
  if (content.includes("[tool.pytest"))
38018
38420
  return "pytest";
38019
38421
  if (content.includes("pytest"))
38020
38422
  return "pytest";
38021
38423
  }
38022
- if (fs10.existsSync(setupCfgPath)) {
38023
- const content = fs10.readFileSync(setupCfgPath, "utf-8");
38424
+ if (fs12.existsSync(setupCfgPath)) {
38425
+ const content = fs12.readFileSync(setupCfgPath, "utf-8");
38024
38426
  if (content.includes("[pytest]"))
38025
38427
  return "pytest";
38026
38428
  }
38027
- if (fs10.existsSync(requirementsTxtPath)) {
38028
- const content = fs10.readFileSync(requirementsTxtPath, "utf-8");
38429
+ if (fs12.existsSync(requirementsTxtPath)) {
38430
+ const content = fs12.readFileSync(requirementsTxtPath, "utf-8");
38029
38431
  if (content.includes("pytest"))
38030
38432
  return "pytest";
38031
38433
  }
38032
38434
  } catch {}
38033
38435
  try {
38034
- const cargoTomlPath = path20.join(baseDir, "Cargo.toml");
38035
- if (fs10.existsSync(cargoTomlPath)) {
38036
- const content = fs10.readFileSync(cargoTomlPath, "utf-8");
38436
+ const cargoTomlPath = path22.join(baseDir, "Cargo.toml");
38437
+ if (fs12.existsSync(cargoTomlPath)) {
38438
+ const content = fs12.readFileSync(cargoTomlPath, "utf-8");
38037
38439
  if (content.includes("[dev-dependencies]")) {
38038
38440
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
38039
38441
  return "cargo";
@@ -38042,10 +38444,10 @@ async function detectTestFramework(cwd) {
38042
38444
  }
38043
38445
  } catch {}
38044
38446
  try {
38045
- const pesterConfigPath = path20.join(baseDir, "pester.config.ps1");
38046
- const pesterConfigJsonPath = path20.join(baseDir, "pester.config.ps1.json");
38047
- const pesterPs1Path = path20.join(baseDir, "tests.ps1");
38048
- if (fs10.existsSync(pesterConfigPath) || fs10.existsSync(pesterConfigJsonPath) || fs10.existsSync(pesterPs1Path)) {
38447
+ const pesterConfigPath = path22.join(baseDir, "pester.config.ps1");
38448
+ const pesterConfigJsonPath = path22.join(baseDir, "pester.config.ps1.json");
38449
+ const pesterPs1Path = path22.join(baseDir, "tests.ps1");
38450
+ if (fs12.existsSync(pesterConfigPath) || fs12.existsSync(pesterConfigJsonPath) || fs12.existsSync(pesterPs1Path)) {
38049
38451
  return "pester";
38050
38452
  }
38051
38453
  } catch {}
@@ -38096,8 +38498,8 @@ function getTestFilesFromConvention(sourceFiles) {
38096
38498
  const testFiles = [];
38097
38499
  for (const file3 of sourceFiles) {
38098
38500
  const normalizedPath = file3.replace(/\\/g, "/");
38099
- const basename4 = path20.basename(file3);
38100
- const dirname9 = path20.dirname(file3);
38501
+ const basename4 = path22.basename(file3);
38502
+ const dirname9 = path22.dirname(file3);
38101
38503
  if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
38102
38504
  if (!testFiles.includes(file3)) {
38103
38505
  testFiles.push(file3);
@@ -38106,16 +38508,16 @@ function getTestFilesFromConvention(sourceFiles) {
38106
38508
  }
38107
38509
  for (const _pattern of TEST_PATTERNS) {
38108
38510
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
38109
- const ext = path20.extname(basename4);
38511
+ const ext = path22.extname(basename4);
38110
38512
  const possibleTestFiles = [
38111
- path20.join(dirname9, `${nameWithoutExt}.spec${ext}`),
38112
- path20.join(dirname9, `${nameWithoutExt}.test${ext}`),
38113
- path20.join(dirname9, "__tests__", `${nameWithoutExt}${ext}`),
38114
- path20.join(dirname9, "tests", `${nameWithoutExt}${ext}`),
38115
- path20.join(dirname9, "test", `${nameWithoutExt}${ext}`)
38513
+ path22.join(dirname9, `${nameWithoutExt}.spec${ext}`),
38514
+ path22.join(dirname9, `${nameWithoutExt}.test${ext}`),
38515
+ path22.join(dirname9, "__tests__", `${nameWithoutExt}${ext}`),
38516
+ path22.join(dirname9, "tests", `${nameWithoutExt}${ext}`),
38517
+ path22.join(dirname9, "test", `${nameWithoutExt}${ext}`)
38116
38518
  ];
38117
38519
  for (const testFile of possibleTestFiles) {
38118
- if (fs10.existsSync(testFile) && !testFiles.includes(testFile)) {
38520
+ if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
38119
38521
  testFiles.push(testFile);
38120
38522
  }
38121
38523
  }
@@ -38131,8 +38533,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38131
38533
  }
38132
38534
  for (const testFile of candidateTestFiles) {
38133
38535
  try {
38134
- const content = fs10.readFileSync(testFile, "utf-8");
38135
- const testDir = path20.dirname(testFile);
38536
+ const content = fs12.readFileSync(testFile, "utf-8");
38537
+ const testDir = path22.dirname(testFile);
38136
38538
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
38137
38539
  let match;
38138
38540
  match = importRegex.exec(content);
@@ -38140,8 +38542,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38140
38542
  const importPath = match[1];
38141
38543
  let resolvedImport;
38142
38544
  if (importPath.startsWith(".")) {
38143
- resolvedImport = path20.resolve(testDir, importPath);
38144
- const existingExt = path20.extname(resolvedImport);
38545
+ resolvedImport = path22.resolve(testDir, importPath);
38546
+ const existingExt = path22.extname(resolvedImport);
38145
38547
  if (!existingExt) {
38146
38548
  for (const extToTry of [
38147
38549
  ".ts",
@@ -38152,7 +38554,7 @@ async function getTestFilesFromGraph(sourceFiles) {
38152
38554
  ".cjs"
38153
38555
  ]) {
38154
38556
  const withExt = resolvedImport + extToTry;
38155
- if (sourceFiles.includes(withExt) || fs10.existsSync(withExt)) {
38557
+ if (sourceFiles.includes(withExt) || fs12.existsSync(withExt)) {
38156
38558
  resolvedImport = withExt;
38157
38559
  break;
38158
38560
  }
@@ -38161,12 +38563,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38161
38563
  } else {
38162
38564
  continue;
38163
38565
  }
38164
- const importBasename = path20.basename(resolvedImport, path20.extname(resolvedImport));
38165
- const importDir = path20.dirname(resolvedImport);
38566
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38567
+ const importDir = path22.dirname(resolvedImport);
38166
38568
  for (const sourceFile of sourceFiles) {
38167
- const sourceDir = path20.dirname(sourceFile);
38168
- const sourceBasename = path20.basename(sourceFile, path20.extname(sourceFile));
38169
- const isRelatedDir = importDir === sourceDir || importDir === path20.join(sourceDir, "__tests__") || importDir === path20.join(sourceDir, "tests") || importDir === path20.join(sourceDir, "test");
38569
+ const sourceDir = path22.dirname(sourceFile);
38570
+ const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38571
+ const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38170
38572
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38171
38573
  if (!testFiles.includes(testFile)) {
38172
38574
  testFiles.push(testFile);
@@ -38181,8 +38583,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38181
38583
  while (match !== null) {
38182
38584
  const importPath = match[1];
38183
38585
  if (importPath.startsWith(".")) {
38184
- let resolvedImport = path20.resolve(testDir, importPath);
38185
- const existingExt = path20.extname(resolvedImport);
38586
+ let resolvedImport = path22.resolve(testDir, importPath);
38587
+ const existingExt = path22.extname(resolvedImport);
38186
38588
  if (!existingExt) {
38187
38589
  for (const extToTry of [
38188
38590
  ".ts",
@@ -38193,18 +38595,18 @@ async function getTestFilesFromGraph(sourceFiles) {
38193
38595
  ".cjs"
38194
38596
  ]) {
38195
38597
  const withExt = resolvedImport + extToTry;
38196
- if (sourceFiles.includes(withExt) || fs10.existsSync(withExt)) {
38598
+ if (sourceFiles.includes(withExt) || fs12.existsSync(withExt)) {
38197
38599
  resolvedImport = withExt;
38198
38600
  break;
38199
38601
  }
38200
38602
  }
38201
38603
  }
38202
- const importDir = path20.dirname(resolvedImport);
38203
- const importBasename = path20.basename(resolvedImport, path20.extname(resolvedImport));
38604
+ const importDir = path22.dirname(resolvedImport);
38605
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38204
38606
  for (const sourceFile of sourceFiles) {
38205
- const sourceDir = path20.dirname(sourceFile);
38206
- const sourceBasename = path20.basename(sourceFile, path20.extname(sourceFile));
38207
- const isRelatedDir = importDir === sourceDir || importDir === path20.join(sourceDir, "__tests__") || importDir === path20.join(sourceDir, "tests") || importDir === path20.join(sourceDir, "test");
38607
+ const sourceDir = path22.dirname(sourceFile);
38608
+ const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38609
+ const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38208
38610
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38209
38611
  if (!testFiles.includes(testFile)) {
38210
38612
  testFiles.push(testFile);
@@ -38289,8 +38691,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38289
38691
  return ["mvn", "test"];
38290
38692
  case "gradle": {
38291
38693
  const isWindows = process.platform === "win32";
38292
- const hasGradlewBat = fs10.existsSync(path20.join(baseDir, "gradlew.bat"));
38293
- const hasGradlew = fs10.existsSync(path20.join(baseDir, "gradlew"));
38694
+ const hasGradlewBat = fs12.existsSync(path22.join(baseDir, "gradlew.bat"));
38695
+ const hasGradlew = fs12.existsSync(path22.join(baseDir, "gradlew"));
38294
38696
  if (hasGradlewBat && isWindows)
38295
38697
  return ["gradlew.bat", "test"];
38296
38698
  if (hasGradlew)
@@ -38307,7 +38709,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38307
38709
  "cmake-build-release",
38308
38710
  "out"
38309
38711
  ];
38310
- const actualBuildDir = buildDirCandidates.find((d) => fs10.existsSync(path20.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38712
+ const actualBuildDir = buildDirCandidates.find((d) => fs12.existsSync(path22.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38311
38713
  return ["ctest", "--test-dir", actualBuildDir];
38312
38714
  }
38313
38715
  case "swift-test":
@@ -38849,7 +39251,7 @@ var test_runner = createSwarmTool({
38849
39251
  let effectiveScope = scope;
38850
39252
  if (scope === "all") {} else if (scope === "convention") {
38851
39253
  const sourceFiles = args.files.filter((f) => {
38852
- const ext = path20.extname(f).toLowerCase();
39254
+ const ext = path22.extname(f).toLowerCase();
38853
39255
  return SOURCE_EXTENSIONS.has(ext);
38854
39256
  });
38855
39257
  if (sourceFiles.length === 0) {
@@ -38865,7 +39267,7 @@ var test_runner = createSwarmTool({
38865
39267
  testFiles = getTestFilesFromConvention(sourceFiles);
38866
39268
  } else if (scope === "graph") {
38867
39269
  const sourceFiles = args.files.filter((f) => {
38868
- const ext = path20.extname(f).toLowerCase();
39270
+ const ext = path22.extname(f).toLowerCase();
38869
39271
  return SOURCE_EXTENSIONS.has(ext);
38870
39272
  });
38871
39273
  if (sourceFiles.length === 0) {
@@ -38936,8 +39338,8 @@ function validateDirectoryPath(dir) {
38936
39338
  if (dir.includes("..")) {
38937
39339
  throw new Error("Directory path must not contain path traversal sequences");
38938
39340
  }
38939
- const normalized = path21.normalize(dir);
38940
- const absolutePath = path21.isAbsolute(normalized) ? normalized : path21.resolve(normalized);
39341
+ const normalized = path23.normalize(dir);
39342
+ const absolutePath = path23.isAbsolute(normalized) ? normalized : path23.resolve(normalized);
38941
39343
  return absolutePath;
38942
39344
  }
38943
39345
  function validateTimeout(timeoutMs, defaultValue) {
@@ -38960,9 +39362,9 @@ function validateTimeout(timeoutMs, defaultValue) {
38960
39362
  }
38961
39363
  function getPackageVersion(dir) {
38962
39364
  try {
38963
- const packagePath = path21.join(dir, "package.json");
38964
- if (fs11.existsSync(packagePath)) {
38965
- const content = fs11.readFileSync(packagePath, "utf-8");
39365
+ const packagePath = path23.join(dir, "package.json");
39366
+ if (fs13.existsSync(packagePath)) {
39367
+ const content = fs13.readFileSync(packagePath, "utf-8");
38966
39368
  const pkg = JSON.parse(content);
38967
39369
  return pkg.version ?? null;
38968
39370
  }
@@ -38971,9 +39373,9 @@ function getPackageVersion(dir) {
38971
39373
  }
38972
39374
  function getChangelogVersion(dir) {
38973
39375
  try {
38974
- const changelogPath = path21.join(dir, "CHANGELOG.md");
38975
- if (fs11.existsSync(changelogPath)) {
38976
- const content = fs11.readFileSync(changelogPath, "utf-8");
39376
+ const changelogPath = path23.join(dir, "CHANGELOG.md");
39377
+ if (fs13.existsSync(changelogPath)) {
39378
+ const content = fs13.readFileSync(changelogPath, "utf-8");
38977
39379
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
38978
39380
  if (match) {
38979
39381
  return match[1];
@@ -38985,10 +39387,10 @@ function getChangelogVersion(dir) {
38985
39387
  function getVersionFileVersion(dir) {
38986
39388
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
38987
39389
  for (const file3 of possibleFiles) {
38988
- const filePath = path21.join(dir, file3);
38989
- if (fs11.existsSync(filePath)) {
39390
+ const filePath = path23.join(dir, file3);
39391
+ if (fs13.existsSync(filePath)) {
38990
39392
  try {
38991
- const content = fs11.readFileSync(filePath, "utf-8").trim();
39393
+ const content = fs13.readFileSync(filePath, "utf-8").trim();
38992
39394
  const match = content.match(/(\d+\.\d+\.\d+)/);
38993
39395
  if (match) {
38994
39396
  return match[1];
@@ -39532,7 +39934,7 @@ async function handlePromoteCommand(directory, args) {
39532
39934
  }
39533
39935
 
39534
39936
  // src/commands/reset.ts
39535
- import * as fs12 from "fs";
39937
+ import * as fs14 from "fs";
39536
39938
 
39537
39939
  // src/background/manager.ts
39538
39940
  init_utils();
@@ -40233,8 +40635,8 @@ async function handleResetCommand(directory, args) {
40233
40635
  for (const filename of filesToReset) {
40234
40636
  try {
40235
40637
  const resolvedPath = validateSwarmPath(directory, filename);
40236
- if (fs12.existsSync(resolvedPath)) {
40237
- fs12.unlinkSync(resolvedPath);
40638
+ if (fs14.existsSync(resolvedPath)) {
40639
+ fs14.unlinkSync(resolvedPath);
40238
40640
  results.push(`- \u2705 Deleted ${filename}`);
40239
40641
  } else {
40240
40642
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -40251,8 +40653,8 @@ async function handleResetCommand(directory, args) {
40251
40653
  }
40252
40654
  try {
40253
40655
  const summariesPath = validateSwarmPath(directory, "summaries");
40254
- if (fs12.existsSync(summariesPath)) {
40255
- fs12.rmSync(summariesPath, { recursive: true, force: true });
40656
+ if (fs14.existsSync(summariesPath)) {
40657
+ fs14.rmSync(summariesPath, { recursive: true, force: true });
40256
40658
  results.push("- \u2705 Deleted summaries/ directory");
40257
40659
  } else {
40258
40660
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -40272,14 +40674,14 @@ async function handleResetCommand(directory, args) {
40272
40674
 
40273
40675
  // src/commands/reset-session.ts
40274
40676
  init_utils2();
40275
- import * as fs13 from "fs";
40276
- import * as path22 from "path";
40677
+ import * as fs15 from "fs";
40678
+ import * as path24 from "path";
40277
40679
  async function handleResetSessionCommand(directory, _args) {
40278
40680
  const results = [];
40279
40681
  try {
40280
40682
  const statePath = validateSwarmPath(directory, "session/state.json");
40281
- if (fs13.existsSync(statePath)) {
40282
- fs13.unlinkSync(statePath);
40683
+ if (fs15.existsSync(statePath)) {
40684
+ fs15.unlinkSync(statePath);
40283
40685
  results.push("\u2705 Deleted .swarm/session/state.json");
40284
40686
  } else {
40285
40687
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -40288,15 +40690,15 @@ async function handleResetSessionCommand(directory, _args) {
40288
40690
  results.push("\u274C Failed to delete state.json");
40289
40691
  }
40290
40692
  try {
40291
- const sessionDir = path22.dirname(validateSwarmPath(directory, "session/state.json"));
40292
- if (fs13.existsSync(sessionDir)) {
40293
- const files = fs13.readdirSync(sessionDir);
40693
+ const sessionDir = path24.dirname(validateSwarmPath(directory, "session/state.json"));
40694
+ if (fs15.existsSync(sessionDir)) {
40695
+ const files = fs15.readdirSync(sessionDir);
40294
40696
  const otherFiles = files.filter((f) => f !== "state.json");
40295
40697
  let deletedCount = 0;
40296
40698
  for (const file3 of otherFiles) {
40297
- const filePath = path22.join(sessionDir, file3);
40298
- if (fs13.lstatSync(filePath).isFile()) {
40299
- fs13.unlinkSync(filePath);
40699
+ const filePath = path24.join(sessionDir, file3);
40700
+ if (fs15.lstatSync(filePath).isFile()) {
40701
+ fs15.unlinkSync(filePath);
40300
40702
  deletedCount++;
40301
40703
  }
40302
40704
  }
@@ -40324,7 +40726,7 @@ async function handleResetSessionCommand(directory, _args) {
40324
40726
  // src/summaries/manager.ts
40325
40727
  init_utils2();
40326
40728
  init_utils();
40327
- import * as path23 from "path";
40729
+ import * as path25 from "path";
40328
40730
  var SUMMARY_ID_REGEX = /^S\d+$/;
40329
40731
  function sanitizeSummaryId(id) {
40330
40732
  if (!id || id.length === 0) {
@@ -40348,7 +40750,7 @@ function sanitizeSummaryId(id) {
40348
40750
  }
40349
40751
  async function loadFullOutput(directory, id) {
40350
40752
  const sanitizedId = sanitizeSummaryId(id);
40351
- const relativePath = path23.join("summaries", `${sanitizedId}.json`);
40753
+ const relativePath = path25.join("summaries", `${sanitizedId}.json`);
40352
40754
  validateSwarmPath(directory, relativePath);
40353
40755
  const content = await readSwarmFileAsync(directory, relativePath);
40354
40756
  if (content === null) {
@@ -40401,18 +40803,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
40401
40803
 
40402
40804
  // src/commands/rollback.ts
40403
40805
  init_utils2();
40404
- import * as fs14 from "fs";
40405
- import * as path24 from "path";
40806
+ import * as fs16 from "fs";
40807
+ import * as path26 from "path";
40406
40808
  async function handleRollbackCommand(directory, args) {
40407
40809
  const phaseArg = args[0];
40408
40810
  if (!phaseArg) {
40409
40811
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
40410
- if (!fs14.existsSync(manifestPath2)) {
40812
+ if (!fs16.existsSync(manifestPath2)) {
40411
40813
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
40412
40814
  }
40413
40815
  let manifest2;
40414
40816
  try {
40415
- manifest2 = JSON.parse(fs14.readFileSync(manifestPath2, "utf-8"));
40817
+ manifest2 = JSON.parse(fs16.readFileSync(manifestPath2, "utf-8"));
40416
40818
  } catch {
40417
40819
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
40418
40820
  }
@@ -40434,12 +40836,12 @@ async function handleRollbackCommand(directory, args) {
40434
40836
  return "Error: Phase number must be a positive integer.";
40435
40837
  }
40436
40838
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
40437
- if (!fs14.existsSync(manifestPath)) {
40839
+ if (!fs16.existsSync(manifestPath)) {
40438
40840
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
40439
40841
  }
40440
40842
  let manifest;
40441
40843
  try {
40442
- manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf-8"));
40844
+ manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf-8"));
40443
40845
  } catch {
40444
40846
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
40445
40847
  }
@@ -40449,10 +40851,10 @@ async function handleRollbackCommand(directory, args) {
40449
40851
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
40450
40852
  }
40451
40853
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
40452
- if (!fs14.existsSync(checkpointDir)) {
40854
+ if (!fs16.existsSync(checkpointDir)) {
40453
40855
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
40454
40856
  }
40455
- const checkpointFiles = fs14.readdirSync(checkpointDir);
40857
+ const checkpointFiles = fs16.readdirSync(checkpointDir);
40456
40858
  if (checkpointFiles.length === 0) {
40457
40859
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
40458
40860
  }
@@ -40460,10 +40862,10 @@ async function handleRollbackCommand(directory, args) {
40460
40862
  const successes = [];
40461
40863
  const failures = [];
40462
40864
  for (const file3 of checkpointFiles) {
40463
- const src = path24.join(checkpointDir, file3);
40464
- const dest = path24.join(swarmDir, file3);
40865
+ const src = path26.join(checkpointDir, file3);
40866
+ const dest = path26.join(swarmDir, file3);
40465
40867
  try {
40466
- fs14.cpSync(src, dest, { recursive: true, force: true });
40868
+ fs16.cpSync(src, dest, { recursive: true, force: true });
40467
40869
  successes.push(file3);
40468
40870
  } catch (error93) {
40469
40871
  failures.push({ file: file3, error: error93.message });
@@ -40480,7 +40882,7 @@ async function handleRollbackCommand(directory, args) {
40480
40882
  timestamp: new Date().toISOString()
40481
40883
  };
40482
40884
  try {
40483
- fs14.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40885
+ fs16.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40484
40886
  `);
40485
40887
  } catch (error93) {
40486
40888
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -40523,11 +40925,11 @@ async function handleSimulateCommand(directory, args) {
40523
40925
  ];
40524
40926
  const report = reportLines.filter(Boolean).join(`
40525
40927
  `);
40526
- const fs15 = await import("fs/promises");
40527
- const path25 = await import("path");
40528
- const reportPath = path25.join(directory, ".swarm", "simulate-report.md");
40529
- await fs15.mkdir(path25.dirname(reportPath), { recursive: true });
40530
- await fs15.writeFile(reportPath, report, "utf-8");
40928
+ const fs17 = await import("fs/promises");
40929
+ const path27 = await import("path");
40930
+ const reportPath = path27.join(directory, ".swarm", "simulate-report.md");
40931
+ await fs17.mkdir(path27.dirname(reportPath), { recursive: true });
40932
+ await fs17.writeFile(reportPath, report, "utf-8");
40531
40933
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
40532
40934
  }
40533
40935
 
@@ -41009,18 +41411,18 @@ function resolveCommand(tokens) {
41009
41411
  }
41010
41412
 
41011
41413
  // src/cli/index.ts
41012
- var CONFIG_DIR = path25.join(process.env.XDG_CONFIG_HOME || path25.join(os5.homedir(), ".config"), "opencode");
41013
- var OPENCODE_CONFIG_PATH = path25.join(CONFIG_DIR, "opencode.json");
41014
- var PLUGIN_CONFIG_PATH = path25.join(CONFIG_DIR, "opencode-swarm.json");
41015
- var PROMPTS_DIR = path25.join(CONFIG_DIR, "opencode-swarm");
41414
+ var CONFIG_DIR = path27.join(process.env.XDG_CONFIG_HOME || path27.join(os5.homedir(), ".config"), "opencode");
41415
+ var OPENCODE_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode.json");
41416
+ var PLUGIN_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode-swarm.json");
41417
+ var PROMPTS_DIR = path27.join(CONFIG_DIR, "opencode-swarm");
41016
41418
  function ensureDir(dir) {
41017
- if (!fs15.existsSync(dir)) {
41018
- fs15.mkdirSync(dir, { recursive: true });
41419
+ if (!fs17.existsSync(dir)) {
41420
+ fs17.mkdirSync(dir, { recursive: true });
41019
41421
  }
41020
41422
  }
41021
41423
  function loadJson(filepath) {
41022
41424
  try {
41023
- const content = fs15.readFileSync(filepath, "utf-8");
41425
+ const content = fs17.readFileSync(filepath, "utf-8");
41024
41426
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
41025
41427
  return JSON.parse(stripped);
41026
41428
  } catch {
@@ -41028,7 +41430,7 @@ function loadJson(filepath) {
41028
41430
  }
41029
41431
  }
41030
41432
  function saveJson(filepath, data) {
41031
- fs15.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41433
+ fs17.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41032
41434
  `, "utf-8");
41033
41435
  }
41034
41436
  async function install() {
@@ -41036,7 +41438,7 @@ async function install() {
41036
41438
  `);
41037
41439
  ensureDir(CONFIG_DIR);
41038
41440
  ensureDir(PROMPTS_DIR);
41039
- const LEGACY_CONFIG_PATH = path25.join(CONFIG_DIR, "config.json");
41441
+ const LEGACY_CONFIG_PATH = path27.join(CONFIG_DIR, "config.json");
41040
41442
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41041
41443
  if (!opencodeConfig) {
41042
41444
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -41061,7 +41463,7 @@ async function install() {
41061
41463
  saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
41062
41464
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
41063
41465
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
41064
- if (!fs15.existsSync(PLUGIN_CONFIG_PATH)) {
41466
+ if (!fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41065
41467
  const defaultConfig = {
41066
41468
  agents: {
41067
41469
  coder: { model: "opencode/minimax-m2.5-free" },
@@ -41104,7 +41506,7 @@ async function uninstall() {
41104
41506
  `);
41105
41507
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41106
41508
  if (!opencodeConfig) {
41107
- if (fs15.existsSync(OPENCODE_CONFIG_PATH)) {
41509
+ if (fs17.existsSync(OPENCODE_CONFIG_PATH)) {
41108
41510
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
41109
41511
  return 1;
41110
41512
  } else {
@@ -41136,13 +41538,13 @@ async function uninstall() {
41136
41538
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
41137
41539
  if (process.argv.includes("--clean")) {
41138
41540
  let cleaned = false;
41139
- if (fs15.existsSync(PLUGIN_CONFIG_PATH)) {
41140
- fs15.unlinkSync(PLUGIN_CONFIG_PATH);
41541
+ if (fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41542
+ fs17.unlinkSync(PLUGIN_CONFIG_PATH);
41141
41543
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
41142
41544
  cleaned = true;
41143
41545
  }
41144
- if (fs15.existsSync(PROMPTS_DIR)) {
41145
- fs15.rmSync(PROMPTS_DIR, { recursive: true });
41546
+ if (fs17.existsSync(PROMPTS_DIR)) {
41547
+ fs17.rmSync(PROMPTS_DIR, { recursive: true });
41146
41548
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
41147
41549
  cleaned = true;
41148
41550
  }