opencode-swarm 6.43.2 → 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 path9 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 = path9.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 = path9.join(swarmDir, "plan.md");
16218
- const mdTempPath = path9.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 = path9.resolve(directory, ".swarm");
16306
- const planPath = path9.join(swarmDir, "plan.json");
16307
- const tempPath = path9.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 = path9.join(swarmDir, "plan.md");
16321
- const mdTempPath = path9.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 = path9.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) {
@@ -31620,7 +31998,7 @@ async function handleClarifyCommand(_directory, args) {
31620
31998
  }
31621
31999
 
31622
32000
  // src/commands/close.ts
31623
- import { promises as fs4 } from "fs";
32001
+ import { promises as fs6 } from "fs";
31624
32002
  init_manager();
31625
32003
 
31626
32004
  // src/hooks/knowledge-store.ts
@@ -32256,10 +32634,31 @@ async function runAutoPromotion(directory, config3) {
32256
32634
  // src/commands/close.ts
32257
32635
  init_utils2();
32258
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
+
32259
32658
  // src/session/snapshot-writer.ts
32260
32659
  init_utils2();
32261
- import { mkdirSync as mkdirSync3, renameSync as renameSync2 } from "fs";
32262
- import * as path7 from "path";
32660
+ import { mkdirSync as mkdirSync4, renameSync as renameSync4 } from "fs";
32661
+ import * as path10 from "path";
32263
32662
  init_utils();
32264
32663
  var _writeInFlight = Promise.resolve();
32265
32664
  function serializeAgentSession(s) {
@@ -32346,11 +32745,11 @@ async function writeSnapshot(directory, state) {
32346
32745
  }
32347
32746
  const content = JSON.stringify(snapshot, null, 2);
32348
32747
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
32349
- const dir = path7.dirname(resolvedPath);
32350
- mkdirSync3(dir, { recursive: true });
32748
+ const dir = path10.dirname(resolvedPath);
32749
+ mkdirSync4(dir, { recursive: true });
32351
32750
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
32352
32751
  await Bun.write(tempPath, content);
32353
- renameSync2(tempPath, resolvedPath);
32752
+ renameSync4(tempPath, resolvedPath);
32354
32753
  } catch (error93) {
32355
32754
  log("[snapshot-writer] write failed", {
32356
32755
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -32709,7 +33108,7 @@ async function handleCloseCommand(directory, _args) {
32709
33108
  const planPath = validateSwarmPath(directory, "plan.json");
32710
33109
  let planData;
32711
33110
  try {
32712
- const content = await fs4.readFile(planPath, "utf-8");
33111
+ const content = await fs6.readFile(planPath, "utf-8");
32713
33112
  planData = JSON.parse(content);
32714
33113
  } catch (error93) {
32715
33114
  return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
@@ -32776,7 +33175,7 @@ async function handleCloseCommand(directory, _args) {
32776
33175
  }
32777
33176
  }
32778
33177
  try {
32779
- await fs4.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
33178
+ await fs6.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
32780
33179
  } catch (error93) {
32781
33180
  console.warn("[close-command] Failed to write plan.json:", error93);
32782
33181
  }
@@ -32808,7 +33207,7 @@ async function handleCloseCommand(directory, _args) {
32808
33207
  ].join(`
32809
33208
  `);
32810
33209
  try {
32811
- await fs4.writeFile(closeSummaryPath, summaryContent, "utf-8");
33210
+ await fs6.writeFile(closeSummaryPath, summaryContent, "utf-8");
32812
33211
  } catch (error93) {
32813
33212
  console.warn("[close-command] Failed to write close-summary.md:", error93);
32814
33213
  }
@@ -32817,6 +33216,7 @@ async function handleCloseCommand(directory, _args) {
32817
33216
  } catch (error93) {
32818
33217
  console.warn("[close-command] flushPendingSnapshot error:", error93);
32819
33218
  }
33219
+ await writeCheckpoint(directory).catch(() => {});
32820
33220
  swarmState.agentSessions.clear();
32821
33221
  swarmState.delegationChains.clear();
32822
33222
  const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
@@ -32825,14 +33225,14 @@ async function handleCloseCommand(directory, _args) {
32825
33225
 
32826
33226
  // src/commands/config.ts
32827
33227
  import * as os3 from "os";
32828
- import * as path8 from "path";
33228
+ import * as path11 from "path";
32829
33229
  function getUserConfigDir2() {
32830
- return process.env.XDG_CONFIG_HOME || path8.join(os3.homedir(), ".config");
33230
+ return process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config");
32831
33231
  }
32832
33232
  async function handleConfigCommand(directory, _args) {
32833
33233
  const config3 = loadPluginConfig(directory);
32834
- const userConfigPath = path8.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
32835
- 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");
32836
33236
  const lines = [
32837
33237
  "## Swarm Configuration",
32838
33238
  "",
@@ -32850,7 +33250,7 @@ async function handleConfigCommand(directory, _args) {
32850
33250
  }
32851
33251
 
32852
33252
  // src/hooks/hive-promoter.ts
32853
- import path10 from "path";
33253
+ import path12 from "path";
32854
33254
 
32855
33255
  // src/background/event-bus.ts
32856
33256
  init_utils();
@@ -33105,7 +33505,7 @@ async function promoteToHive(directory, lesson, category) {
33105
33505
  schema_version: 1,
33106
33506
  created_at: new Date().toISOString(),
33107
33507
  updated_at: new Date().toISOString(),
33108
- source_project: path10.basename(directory) || "unknown",
33508
+ source_project: path12.basename(directory) || "unknown",
33109
33509
  encounter_score: 1
33110
33510
  };
33111
33511
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -33183,13 +33583,13 @@ function formatCurationSummary(summary) {
33183
33583
  }
33184
33584
 
33185
33585
  // src/commands/dark-matter.ts
33186
- import path12 from "path";
33586
+ import path14 from "path";
33187
33587
 
33188
33588
  // src/tools/co-change-analyzer.ts
33189
33589
  import * as child_process from "child_process";
33190
33590
  import { randomUUID } from "crypto";
33191
33591
  import { readdir, readFile as readFile2, stat } from "fs/promises";
33192
- import * as path11 from "path";
33592
+ import * as path13 from "path";
33193
33593
  import { promisify } from "util";
33194
33594
  function getExecFileAsync() {
33195
33595
  return promisify(child_process.execFile);
@@ -33291,7 +33691,7 @@ async function scanSourceFiles(dir) {
33291
33691
  try {
33292
33692
  const entries = await readdir(dir, { withFileTypes: true });
33293
33693
  for (const entry of entries) {
33294
- const fullPath = path11.join(dir, entry.name);
33694
+ const fullPath = path13.join(dir, entry.name);
33295
33695
  if (entry.isDirectory()) {
33296
33696
  if (skipDirs.has(entry.name)) {
33297
33697
  continue;
@@ -33299,7 +33699,7 @@ async function scanSourceFiles(dir) {
33299
33699
  const subFiles = await scanSourceFiles(fullPath);
33300
33700
  results.push(...subFiles);
33301
33701
  } else if (entry.isFile()) {
33302
- const ext = path11.extname(entry.name);
33702
+ const ext = path13.extname(entry.name);
33303
33703
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
33304
33704
  results.push(fullPath);
33305
33705
  }
@@ -33321,8 +33721,8 @@ async function getStaticEdges(directory) {
33321
33721
  continue;
33322
33722
  }
33323
33723
  try {
33324
- const sourceDir = path11.dirname(sourceFile);
33325
- const resolvedPath = path11.resolve(sourceDir, importPath);
33724
+ const sourceDir = path13.dirname(sourceFile);
33725
+ const resolvedPath = path13.resolve(sourceDir, importPath);
33326
33726
  const extensions = [
33327
33727
  "",
33328
33728
  ".ts",
@@ -33347,8 +33747,8 @@ async function getStaticEdges(directory) {
33347
33747
  if (!targetFile) {
33348
33748
  continue;
33349
33749
  }
33350
- const relSource = path11.relative(directory, sourceFile).replace(/\\/g, "/");
33351
- const relTarget = path11.relative(directory, targetFile).replace(/\\/g, "/");
33750
+ const relSource = path13.relative(directory, sourceFile).replace(/\\/g, "/");
33751
+ const relTarget = path13.relative(directory, targetFile).replace(/\\/g, "/");
33352
33752
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
33353
33753
  edges.add(key);
33354
33754
  } catch {}
@@ -33360,7 +33760,7 @@ async function getStaticEdges(directory) {
33360
33760
  function isTestImplementationPair(fileA, fileB) {
33361
33761
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
33362
33762
  const getBaseName = (filePath) => {
33363
- const base = path11.basename(filePath);
33763
+ const base = path13.basename(filePath);
33364
33764
  for (const pattern of testPatterns) {
33365
33765
  if (base.endsWith(pattern)) {
33366
33766
  return base.slice(0, -pattern.length);
@@ -33370,16 +33770,16 @@ function isTestImplementationPair(fileA, fileB) {
33370
33770
  };
33371
33771
  const baseA = getBaseName(fileA);
33372
33772
  const baseB = getBaseName(fileB);
33373
- return baseA === baseB && baseA !== path11.basename(fileA) && baseA !== path11.basename(fileB);
33773
+ return baseA === baseB && baseA !== path13.basename(fileA) && baseA !== path13.basename(fileB);
33374
33774
  }
33375
33775
  function hasSharedPrefix(fileA, fileB) {
33376
- const dirA = path11.dirname(fileA);
33377
- const dirB = path11.dirname(fileB);
33776
+ const dirA = path13.dirname(fileA);
33777
+ const dirB = path13.dirname(fileB);
33378
33778
  if (dirA !== dirB) {
33379
33779
  return false;
33380
33780
  }
33381
- const baseA = path11.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33382
- const baseB = path11.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)$/, "");
33383
33783
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
33384
33784
  return true;
33385
33785
  }
@@ -33433,8 +33833,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
33433
33833
  const entries = [];
33434
33834
  const now = new Date().toISOString();
33435
33835
  for (const pair of pairs.slice(0, 10)) {
33436
- const baseA = path11.basename(pair.fileA);
33437
- const baseB = path11.basename(pair.fileB);
33836
+ const baseA = path13.basename(pair.fileA);
33837
+ const baseB = path13.basename(pair.fileB);
33438
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.`;
33439
33839
  if (lesson.length > 280) {
33440
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.`;
@@ -33544,7 +33944,7 @@ async function handleDarkMatterCommand(directory, args) {
33544
33944
  const output = formatDarkMatterOutput(pairs);
33545
33945
  if (pairs.length > 0) {
33546
33946
  try {
33547
- const projectName = path12.basename(path12.resolve(directory));
33947
+ const projectName = path14.basename(path14.resolve(directory));
33548
33948
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
33549
33949
  if (entries.length > 0) {
33550
33950
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -33565,8 +33965,8 @@ async function handleDarkMatterCommand(directory, args) {
33565
33965
 
33566
33966
  // src/services/diagnose-service.ts
33567
33967
  import { execSync } from "child_process";
33568
- import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
33569
- 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";
33570
33970
  import { fileURLToPath } from "url";
33571
33971
  init_manager();
33572
33972
  init_utils2();
@@ -33802,7 +34202,7 @@ async function checkConfigBackups(directory) {
33802
34202
  }
33803
34203
  async function checkGitRepository(directory) {
33804
34204
  try {
33805
- if (!existsSync4(directory) || !statSync3(directory).isDirectory()) {
34205
+ if (!existsSync5(directory) || !statSync3(directory).isDirectory()) {
33806
34206
  return {
33807
34207
  name: "Git Repository",
33808
34208
  status: "\u274C",
@@ -33863,8 +34263,8 @@ async function checkSpecStaleness(directory, plan) {
33863
34263
  };
33864
34264
  }
33865
34265
  async function checkConfigParseability(directory) {
33866
- const configPath = path13.join(directory, ".opencode/opencode-swarm.json");
33867
- if (!existsSync4(configPath)) {
34266
+ const configPath = path15.join(directory, ".opencode/opencode-swarm.json");
34267
+ if (!existsSync5(configPath)) {
33868
34268
  return {
33869
34269
  name: "Config Parseability",
33870
34270
  status: "\u2705",
@@ -33872,7 +34272,7 @@ async function checkConfigParseability(directory) {
33872
34272
  };
33873
34273
  }
33874
34274
  try {
33875
- const content = readFileSync3(configPath, "utf-8");
34275
+ const content = readFileSync5(configPath, "utf-8");
33876
34276
  JSON.parse(content);
33877
34277
  return {
33878
34278
  name: "Config Parseability",
@@ -33910,15 +34310,15 @@ async function checkGrammarWasmFiles() {
33910
34310
  "tree-sitter-ini.wasm",
33911
34311
  "tree-sitter-regex.wasm"
33912
34312
  ];
33913
- const thisDir = path13.dirname(fileURLToPath(import.meta.url));
34313
+ const thisDir = path15.dirname(fileURLToPath(import.meta.url));
33914
34314
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
33915
- 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");
33916
34316
  const missing = [];
33917
- if (!existsSync4(path13.join(grammarDir, "tree-sitter.wasm"))) {
34317
+ if (!existsSync5(path15.join(grammarDir, "tree-sitter.wasm"))) {
33918
34318
  missing.push("tree-sitter.wasm (core runtime)");
33919
34319
  }
33920
34320
  for (const file3 of grammarFiles) {
33921
- if (!existsSync4(path13.join(grammarDir, file3))) {
34321
+ if (!existsSync5(path15.join(grammarDir, file3))) {
33922
34322
  missing.push(file3);
33923
34323
  }
33924
34324
  }
@@ -33936,8 +34336,8 @@ async function checkGrammarWasmFiles() {
33936
34336
  };
33937
34337
  }
33938
34338
  async function checkCheckpointManifest(directory) {
33939
- const manifestPath = path13.join(directory, ".swarm/checkpoints.json");
33940
- if (!existsSync4(manifestPath)) {
34339
+ const manifestPath = path15.join(directory, ".swarm/checkpoints.json");
34340
+ if (!existsSync5(manifestPath)) {
33941
34341
  return {
33942
34342
  name: "Checkpoint Manifest",
33943
34343
  status: "\u2705",
@@ -33945,7 +34345,7 @@ async function checkCheckpointManifest(directory) {
33945
34345
  };
33946
34346
  }
33947
34347
  try {
33948
- const content = readFileSync3(manifestPath, "utf-8");
34348
+ const content = readFileSync5(manifestPath, "utf-8");
33949
34349
  const parsed = JSON.parse(content);
33950
34350
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
33951
34351
  return {
@@ -33988,8 +34388,8 @@ async function checkCheckpointManifest(directory) {
33988
34388
  }
33989
34389
  }
33990
34390
  async function checkEventStreamIntegrity(directory) {
33991
- const eventsPath = path13.join(directory, ".swarm/events.jsonl");
33992
- if (!existsSync4(eventsPath)) {
34391
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34392
+ if (!existsSync5(eventsPath)) {
33993
34393
  return {
33994
34394
  name: "Event Stream",
33995
34395
  status: "\u2705",
@@ -33997,7 +34397,7 @@ async function checkEventStreamIntegrity(directory) {
33997
34397
  };
33998
34398
  }
33999
34399
  try {
34000
- const content = readFileSync3(eventsPath, "utf-8");
34400
+ const content = readFileSync5(eventsPath, "utf-8");
34001
34401
  const lines = content.split(`
34002
34402
  `).filter((line) => line.trim() !== "");
34003
34403
  let malformedCount = 0;
@@ -34029,8 +34429,8 @@ async function checkEventStreamIntegrity(directory) {
34029
34429
  }
34030
34430
  }
34031
34431
  async function checkSteeringDirectives(directory) {
34032
- const eventsPath = path13.join(directory, ".swarm/events.jsonl");
34033
- if (!existsSync4(eventsPath)) {
34432
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34433
+ if (!existsSync5(eventsPath)) {
34034
34434
  return {
34035
34435
  name: "Steering Directives",
34036
34436
  status: "\u2705",
@@ -34038,7 +34438,7 @@ async function checkSteeringDirectives(directory) {
34038
34438
  };
34039
34439
  }
34040
34440
  try {
34041
- const content = readFileSync3(eventsPath, "utf-8");
34441
+ const content = readFileSync5(eventsPath, "utf-8");
34042
34442
  const lines = content.split(`
34043
34443
  `).filter((line) => line.trim() !== "");
34044
34444
  const directivesIssued = [];
@@ -34085,8 +34485,8 @@ async function checkCurator(directory) {
34085
34485
  detail: "Disabled (enable via curator.enabled)"
34086
34486
  };
34087
34487
  }
34088
- const summaryPath = path13.join(directory, ".swarm/curator-summary.json");
34089
- if (!existsSync4(summaryPath)) {
34488
+ const summaryPath = path15.join(directory, ".swarm/curator-summary.json");
34489
+ if (!existsSync5(summaryPath)) {
34090
34490
  return {
34091
34491
  name: "Curator",
34092
34492
  status: "\u2705",
@@ -34094,7 +34494,7 @@ async function checkCurator(directory) {
34094
34494
  };
34095
34495
  }
34096
34496
  try {
34097
- const content = readFileSync3(summaryPath, "utf-8");
34497
+ const content = readFileSync5(summaryPath, "utf-8");
34098
34498
  const parsed = JSON.parse(content);
34099
34499
  if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
34100
34500
  return {
@@ -34524,8 +34924,8 @@ async function handleExportCommand(directory, _args) {
34524
34924
  }
34525
34925
  // src/commands/handoff.ts
34526
34926
  init_utils2();
34527
- import crypto3 from "crypto";
34528
- import { renameSync as renameSync4 } from "fs";
34927
+ import crypto4 from "crypto";
34928
+ import { renameSync as renameSync5 } from "fs";
34529
34929
 
34530
34930
  // src/services/handoff-service.ts
34531
34931
  init_utils2();
@@ -34833,9 +35233,9 @@ async function handleHandoffCommand(directory, _args) {
34833
35233
  const handoffData = await getHandoffData(directory);
34834
35234
  const markdown = formatHandoffMarkdown(handoffData);
34835
35235
  const resolvedPath = validateSwarmPath(directory, "handoff.md");
34836
- const tempPath = `${resolvedPath}.tmp.${crypto3.randomUUID()}`;
35236
+ const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
34837
35237
  await Bun.write(tempPath, markdown);
34838
- renameSync4(tempPath, resolvedPath);
35238
+ renameSync5(tempPath, resolvedPath);
34839
35239
  await writeSnapshot(directory, swarmState);
34840
35240
  await flushPendingSnapshot(directory);
34841
35241
  return `## Handoff Brief Written
@@ -34980,14 +35380,14 @@ async function handleHistoryCommand(directory, _args) {
34980
35380
  }
34981
35381
  // src/hooks/knowledge-migrator.ts
34982
35382
  import { randomUUID as randomUUID2 } from "crypto";
34983
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
35383
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
34984
35384
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
34985
- import * as path15 from "path";
35385
+ import * as path17 from "path";
34986
35386
  async function migrateContextToKnowledge(directory, config3) {
34987
- const sentinelPath = path15.join(directory, ".swarm", ".knowledge-migrated");
34988
- 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");
34989
35389
  const knowledgePath = resolveSwarmKnowledgePath(directory);
34990
- if (existsSync6(sentinelPath)) {
35390
+ if (existsSync7(sentinelPath)) {
34991
35391
  return {
34992
35392
  migrated: false,
34993
35393
  entriesMigrated: 0,
@@ -34996,7 +35396,7 @@ async function migrateContextToKnowledge(directory, config3) {
34996
35396
  skippedReason: "sentinel-exists"
34997
35397
  };
34998
35398
  }
34999
- if (!existsSync6(contextPath)) {
35399
+ if (!existsSync7(contextPath)) {
35000
35400
  return {
35001
35401
  migrated: false,
35002
35402
  entriesMigrated: 0,
@@ -35181,16 +35581,16 @@ function truncateLesson(text) {
35181
35581
  return `${text.slice(0, 277)}...`;
35182
35582
  }
35183
35583
  function inferProjectName(directory) {
35184
- const packageJsonPath = path15.join(directory, "package.json");
35185
- if (existsSync6(packageJsonPath)) {
35584
+ const packageJsonPath = path17.join(directory, "package.json");
35585
+ if (existsSync7(packageJsonPath)) {
35186
35586
  try {
35187
- const pkg = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
35587
+ const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
35188
35588
  if (pkg.name && typeof pkg.name === "string") {
35189
35589
  return pkg.name;
35190
35590
  }
35191
35591
  } catch {}
35192
35592
  }
35193
- return path15.basename(directory);
35593
+ return path17.basename(directory);
35194
35594
  }
35195
35595
  async function writeSentinel(sentinelPath, migrated, dropped) {
35196
35596
  const sentinel = {
@@ -35202,7 +35602,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
35202
35602
  schema_version: 1,
35203
35603
  migration_tool: "knowledge-migrator.ts"
35204
35604
  };
35205
- await mkdir3(path15.dirname(sentinelPath), { recursive: true });
35605
+ await mkdir3(path17.dirname(sentinelPath), { recursive: true });
35206
35606
  await writeFile3(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
35207
35607
  }
35208
35608
 
@@ -35438,20 +35838,20 @@ async function handlePlanCommand(directory, args) {
35438
35838
  // src/services/preflight-service.ts
35439
35839
  init_manager();
35440
35840
  init_manager2();
35441
- import * as fs11 from "fs";
35442
- import * as path21 from "path";
35841
+ import * as fs13 from "fs";
35842
+ import * as path23 from "path";
35443
35843
 
35444
35844
  // src/tools/lint.ts
35445
- import * as fs7 from "fs";
35446
- import * as path17 from "path";
35845
+ import * as fs9 from "fs";
35846
+ import * as path19 from "path";
35447
35847
 
35448
35848
  // src/build/discovery.ts
35449
- import * as fs6 from "fs";
35450
- import * as path16 from "path";
35849
+ import * as fs8 from "fs";
35850
+ import * as path18 from "path";
35451
35851
 
35452
35852
  // src/lang/detector.ts
35453
35853
  import { access, readdir as readdir2 } from "fs/promises";
35454
- import { extname as extname2, join as join11 } from "path";
35854
+ import { extname as extname2, join as join13 } from "path";
35455
35855
 
35456
35856
  // src/lang/profiles.ts
35457
35857
  class LanguageRegistry {
@@ -36376,7 +36776,7 @@ async function detectProjectLanguages(projectDir) {
36376
36776
  if (detectFile.includes("*") || detectFile.includes("?"))
36377
36777
  continue;
36378
36778
  try {
36379
- await access(join11(dir, detectFile));
36779
+ await access(join13(dir, detectFile));
36380
36780
  detected.add(profile.id);
36381
36781
  break;
36382
36782
  } catch {}
@@ -36397,7 +36797,7 @@ async function detectProjectLanguages(projectDir) {
36397
36797
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
36398
36798
  for (const entry of topEntries) {
36399
36799
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
36400
- await scanDir(join11(projectDir, entry.name));
36800
+ await scanDir(join13(projectDir, entry.name));
36401
36801
  }
36402
36802
  }
36403
36803
  } catch {}
@@ -36540,16 +36940,16 @@ function findBuildFiles(workingDir, patterns) {
36540
36940
  if (pattern.includes("*")) {
36541
36941
  const dir = workingDir;
36542
36942
  try {
36543
- const files = fs6.readdirSync(dir);
36943
+ const files = fs8.readdirSync(dir);
36544
36944
  const regex = simpleGlobToRegex(pattern);
36545
36945
  const matches = files.filter((f) => regex.test(f));
36546
36946
  if (matches.length > 0) {
36547
- return path16.join(dir, matches[0]);
36947
+ return path18.join(dir, matches[0]);
36548
36948
  }
36549
36949
  } catch {}
36550
36950
  } else {
36551
- const filePath = path16.join(workingDir, pattern);
36552
- if (fs6.existsSync(filePath)) {
36951
+ const filePath = path18.join(workingDir, pattern);
36952
+ if (fs8.existsSync(filePath)) {
36553
36953
  return filePath;
36554
36954
  }
36555
36955
  }
@@ -36557,12 +36957,12 @@ function findBuildFiles(workingDir, patterns) {
36557
36957
  return null;
36558
36958
  }
36559
36959
  function getRepoDefinedScripts(workingDir, scripts) {
36560
- const packageJsonPath = path16.join(workingDir, "package.json");
36561
- if (!fs6.existsSync(packageJsonPath)) {
36960
+ const packageJsonPath = path18.join(workingDir, "package.json");
36961
+ if (!fs8.existsSync(packageJsonPath)) {
36562
36962
  return [];
36563
36963
  }
36564
36964
  try {
36565
- const content = fs6.readFileSync(packageJsonPath, "utf-8");
36965
+ const content = fs8.readFileSync(packageJsonPath, "utf-8");
36566
36966
  const pkg = JSON.parse(content);
36567
36967
  if (!pkg.scripts || typeof pkg.scripts !== "object") {
36568
36968
  return [];
@@ -36598,8 +36998,8 @@ function findAllBuildFiles(workingDir) {
36598
36998
  const regex = simpleGlobToRegex(pattern);
36599
36999
  findFilesRecursive(workingDir, regex, allBuildFiles);
36600
37000
  } else {
36601
- const filePath = path16.join(workingDir, pattern);
36602
- if (fs6.existsSync(filePath)) {
37001
+ const filePath = path18.join(workingDir, pattern);
37002
+ if (fs8.existsSync(filePath)) {
36603
37003
  allBuildFiles.add(filePath);
36604
37004
  }
36605
37005
  }
@@ -36609,9 +37009,9 @@ function findAllBuildFiles(workingDir) {
36609
37009
  }
36610
37010
  function findFilesRecursive(dir, regex, results) {
36611
37011
  try {
36612
- const entries = fs6.readdirSync(dir, { withFileTypes: true });
37012
+ const entries = fs8.readdirSync(dir, { withFileTypes: true });
36613
37013
  for (const entry of entries) {
36614
- const fullPath = path16.join(dir, entry.name);
37014
+ const fullPath = path18.join(dir, entry.name);
36615
37015
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
36616
37016
  findFilesRecursive(fullPath, regex, results);
36617
37017
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -36634,8 +37034,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
36634
37034
  let foundCommand = false;
36635
37035
  for (const cmd of sortedCommands) {
36636
37036
  if (cmd.detectFile) {
36637
- const detectFilePath = path16.join(workingDir, cmd.detectFile);
36638
- if (!fs6.existsSync(detectFilePath)) {
37037
+ const detectFilePath = path18.join(workingDir, cmd.detectFile);
37038
+ if (!fs8.existsSync(detectFilePath)) {
36639
37039
  continue;
36640
37040
  }
36641
37041
  }
@@ -36782,9 +37182,9 @@ function validateArgs(args) {
36782
37182
  }
36783
37183
  function getLinterCommand(linter, mode, projectDir) {
36784
37184
  const isWindows = process.platform === "win32";
36785
- const binDir = path17.join(projectDir, "node_modules", ".bin");
36786
- const biomeBin = isWindows ? path17.join(binDir, "biome.EXE") : path17.join(binDir, "biome");
36787
- 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");
36788
37188
  switch (linter) {
36789
37189
  case "biome":
36790
37190
  if (mode === "fix") {
@@ -36800,7 +37200,7 @@ function getLinterCommand(linter, mode, projectDir) {
36800
37200
  }
36801
37201
  function getAdditionalLinterCommand(linter, mode, cwd) {
36802
37202
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
36803
- 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;
36804
37204
  switch (linter) {
36805
37205
  case "ruff":
36806
37206
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -36834,12 +37234,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
36834
37234
  }
36835
37235
  }
36836
37236
  function detectRuff(cwd) {
36837
- if (fs7.existsSync(path17.join(cwd, "ruff.toml")))
37237
+ if (fs9.existsSync(path19.join(cwd, "ruff.toml")))
36838
37238
  return isCommandAvailable("ruff");
36839
37239
  try {
36840
- const pyproject = path17.join(cwd, "pyproject.toml");
36841
- if (fs7.existsSync(pyproject)) {
36842
- 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");
36843
37243
  if (content.includes("[tool.ruff]"))
36844
37244
  return isCommandAvailable("ruff");
36845
37245
  }
@@ -36847,21 +37247,21 @@ function detectRuff(cwd) {
36847
37247
  return false;
36848
37248
  }
36849
37249
  function detectClippy(cwd) {
36850
- return fs7.existsSync(path17.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37250
+ return fs9.existsSync(path19.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
36851
37251
  }
36852
37252
  function detectGolangciLint(cwd) {
36853
- return fs7.existsSync(path17.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37253
+ return fs9.existsSync(path19.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
36854
37254
  }
36855
37255
  function detectCheckstyle(cwd) {
36856
- const hasMaven = fs7.existsSync(path17.join(cwd, "pom.xml"));
36857
- const hasGradle = fs7.existsSync(path17.join(cwd, "build.gradle")) || fs7.existsSync(path17.join(cwd, "build.gradle.kts"));
36858
- 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"));
36859
37259
  return (hasMaven || hasGradle) && hasBinary;
36860
37260
  }
36861
37261
  function detectKtlint(cwd) {
36862
- 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")) || (() => {
36863
37263
  try {
36864
- 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"));
36865
37265
  } catch {
36866
37266
  return false;
36867
37267
  }
@@ -36870,7 +37270,7 @@ function detectKtlint(cwd) {
36870
37270
  }
36871
37271
  function detectDotnetFormat(cwd) {
36872
37272
  try {
36873
- const files = fs7.readdirSync(cwd);
37273
+ const files = fs9.readdirSync(cwd);
36874
37274
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
36875
37275
  return hasCsproj && isCommandAvailable("dotnet");
36876
37276
  } catch {
@@ -36878,14 +37278,14 @@ function detectDotnetFormat(cwd) {
36878
37278
  }
36879
37279
  }
36880
37280
  function detectCppcheck(cwd) {
36881
- if (fs7.existsSync(path17.join(cwd, "CMakeLists.txt"))) {
37281
+ if (fs9.existsSync(path19.join(cwd, "CMakeLists.txt"))) {
36882
37282
  return isCommandAvailable("cppcheck");
36883
37283
  }
36884
37284
  try {
36885
- const dirsToCheck = [cwd, path17.join(cwd, "src")];
37285
+ const dirsToCheck = [cwd, path19.join(cwd, "src")];
36886
37286
  const hasCpp = dirsToCheck.some((dir) => {
36887
37287
  try {
36888
- 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));
36889
37289
  } catch {
36890
37290
  return false;
36891
37291
  }
@@ -36896,13 +37296,13 @@ function detectCppcheck(cwd) {
36896
37296
  }
36897
37297
  }
36898
37298
  function detectSwiftlint(cwd) {
36899
- return fs7.existsSync(path17.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37299
+ return fs9.existsSync(path19.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
36900
37300
  }
36901
37301
  function detectDartAnalyze(cwd) {
36902
- 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"));
36903
37303
  }
36904
37304
  function detectRubocop(cwd) {
36905
- 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"));
36906
37306
  }
36907
37307
  function detectAdditionalLinter(cwd) {
36908
37308
  if (detectRuff(cwd))
@@ -36931,12 +37331,12 @@ async function detectAvailableLinter(directory) {
36931
37331
  const _DETECT_TIMEOUT = 2000;
36932
37332
  if (!directory)
36933
37333
  return null;
36934
- if (!fs7.existsSync(directory))
37334
+ if (!fs9.existsSync(directory))
36935
37335
  return null;
36936
37336
  const projectDir = directory;
36937
37337
  const isWindows = process.platform === "win32";
36938
- const biomeBin = isWindows ? path17.join(projectDir, "node_modules", ".bin", "biome.EXE") : path17.join(projectDir, "node_modules", ".bin", "biome");
36939
- 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");
36940
37340
  return _detectAvailableLinter(projectDir, biomeBin, eslintBin);
36941
37341
  }
36942
37342
  async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
@@ -36951,7 +37351,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36951
37351
  const result = await Promise.race([biomeExit, timeout]);
36952
37352
  if (result === "timeout") {
36953
37353
  biomeProc.kill();
36954
- } else if (biomeProc.exitCode === 0 && fs7.existsSync(biomeBin)) {
37354
+ } else if (biomeProc.exitCode === 0 && fs9.existsSync(biomeBin)) {
36955
37355
  return "biome";
36956
37356
  }
36957
37357
  } catch {}
@@ -36965,7 +37365,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36965
37365
  const result = await Promise.race([eslintExit, timeout]);
36966
37366
  if (result === "timeout") {
36967
37367
  eslintProc.kill();
36968
- } else if (eslintProc.exitCode === 0 && fs7.existsSync(eslintBin)) {
37368
+ } else if (eslintProc.exitCode === 0 && fs9.existsSync(eslintBin)) {
36969
37369
  return "eslint";
36970
37370
  }
36971
37371
  } catch {}
@@ -37135,8 +37535,8 @@ For Rust: rustup component add clippy`
37135
37535
  });
37136
37536
 
37137
37537
  // src/tools/secretscan.ts
37138
- import * as fs8 from "fs";
37139
- import * as path18 from "path";
37538
+ import * as fs10 from "fs";
37539
+ import * as path20 from "path";
37140
37540
  var MAX_FILE_PATH_LENGTH = 500;
37141
37541
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
37142
37542
  var MAX_FILES_SCANNED = 1000;
@@ -37363,11 +37763,11 @@ function isGlobOrPathPattern(pattern) {
37363
37763
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
37364
37764
  }
37365
37765
  function loadSecretScanIgnore(scanDir) {
37366
- const ignorePath = path18.join(scanDir, ".secretscanignore");
37766
+ const ignorePath = path20.join(scanDir, ".secretscanignore");
37367
37767
  try {
37368
- if (!fs8.existsSync(ignorePath))
37768
+ if (!fs10.existsSync(ignorePath))
37369
37769
  return [];
37370
- const content = fs8.readFileSync(ignorePath, "utf8");
37770
+ const content = fs10.readFileSync(ignorePath, "utf8");
37371
37771
  const patterns = [];
37372
37772
  for (const rawLine of content.split(/\r?\n/)) {
37373
37773
  const line = rawLine.trim();
@@ -37386,7 +37786,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
37386
37786
  if (exactNames.has(entry))
37387
37787
  return true;
37388
37788
  for (const pattern of globPatterns) {
37389
- if (path18.matchesGlob(relPath, pattern))
37789
+ if (path20.matchesGlob(relPath, pattern))
37390
37790
  return true;
37391
37791
  }
37392
37792
  return false;
@@ -37407,7 +37807,7 @@ function validateDirectoryInput(dir) {
37407
37807
  return null;
37408
37808
  }
37409
37809
  function isBinaryFile(filePath, buffer) {
37410
- const ext = path18.extname(filePath).toLowerCase();
37810
+ const ext = path20.extname(filePath).toLowerCase();
37411
37811
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37412
37812
  return true;
37413
37813
  }
@@ -37482,11 +37882,11 @@ function createRedactedContext(line, findings) {
37482
37882
  result += line.slice(lastEnd);
37483
37883
  return result;
37484
37884
  }
37485
- var O_NOFOLLOW = process.platform !== "win32" ? fs8.constants.O_NOFOLLOW : undefined;
37885
+ var O_NOFOLLOW = process.platform !== "win32" ? fs10.constants.O_NOFOLLOW : undefined;
37486
37886
  function scanFileForSecrets(filePath) {
37487
37887
  const findings = [];
37488
37888
  try {
37489
- const lstat = fs8.lstatSync(filePath);
37889
+ const lstat = fs10.lstatSync(filePath);
37490
37890
  if (lstat.isSymbolicLink()) {
37491
37891
  return findings;
37492
37892
  }
@@ -37495,14 +37895,14 @@ function scanFileForSecrets(filePath) {
37495
37895
  }
37496
37896
  let buffer;
37497
37897
  if (O_NOFOLLOW !== undefined) {
37498
- const fd = fs8.openSync(filePath, "r", O_NOFOLLOW);
37898
+ const fd = fs10.openSync(filePath, "r", O_NOFOLLOW);
37499
37899
  try {
37500
- buffer = fs8.readFileSync(fd);
37900
+ buffer = fs10.readFileSync(fd);
37501
37901
  } finally {
37502
- fs8.closeSync(fd);
37902
+ fs10.closeSync(fd);
37503
37903
  }
37504
37904
  } else {
37505
- buffer = fs8.readFileSync(filePath);
37905
+ buffer = fs10.readFileSync(filePath);
37506
37906
  }
37507
37907
  if (isBinaryFile(filePath, buffer)) {
37508
37908
  return findings;
@@ -37544,9 +37944,9 @@ function isSymlinkLoop(realPath, visited) {
37544
37944
  return false;
37545
37945
  }
37546
37946
  function isPathWithinScope(realPath, scanDir) {
37547
- const resolvedScanDir = path18.resolve(scanDir);
37548
- const resolvedRealPath = path18.resolve(realPath);
37549
- 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}\\`);
37550
37950
  }
37551
37951
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
37552
37952
  skippedDirs: 0,
@@ -37557,7 +37957,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37557
37957
  const files = [];
37558
37958
  let entries;
37559
37959
  try {
37560
- entries = fs8.readdirSync(dir);
37960
+ entries = fs10.readdirSync(dir);
37561
37961
  } catch {
37562
37962
  stats.fileErrors++;
37563
37963
  return files;
@@ -37572,15 +37972,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37572
37972
  return a.localeCompare(b);
37573
37973
  });
37574
37974
  for (const entry of entries) {
37575
- const fullPath = path18.join(dir, entry);
37576
- const relPath = path18.relative(scanDir, fullPath).replace(/\\/g, "/");
37975
+ const fullPath = path20.join(dir, entry);
37976
+ const relPath = path20.relative(scanDir, fullPath).replace(/\\/g, "/");
37577
37977
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
37578
37978
  stats.skippedDirs++;
37579
37979
  continue;
37580
37980
  }
37581
37981
  let lstat;
37582
37982
  try {
37583
- lstat = fs8.lstatSync(fullPath);
37983
+ lstat = fs10.lstatSync(fullPath);
37584
37984
  } catch {
37585
37985
  stats.fileErrors++;
37586
37986
  continue;
@@ -37592,7 +37992,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37592
37992
  if (lstat.isDirectory()) {
37593
37993
  let realPath;
37594
37994
  try {
37595
- realPath = fs8.realpathSync(fullPath);
37995
+ realPath = fs10.realpathSync(fullPath);
37596
37996
  } catch {
37597
37997
  stats.fileErrors++;
37598
37998
  continue;
@@ -37608,7 +38008,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37608
38008
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
37609
38009
  files.push(...subFiles);
37610
38010
  } else if (lstat.isFile()) {
37611
- const ext = path18.extname(fullPath).toLowerCase();
38011
+ const ext = path20.extname(fullPath).toLowerCase();
37612
38012
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37613
38013
  files.push(fullPath);
37614
38014
  } else {
@@ -37674,8 +38074,8 @@ var secretscan = createSwarmTool({
37674
38074
  }
37675
38075
  }
37676
38076
  try {
37677
- const scanDir = path18.resolve(directory);
37678
- if (!fs8.existsSync(scanDir)) {
38077
+ const scanDir = path20.resolve(directory);
38078
+ if (!fs10.existsSync(scanDir)) {
37679
38079
  const errorResult = {
37680
38080
  error: "directory not found",
37681
38081
  scan_dir: directory,
@@ -37686,7 +38086,7 @@ var secretscan = createSwarmTool({
37686
38086
  };
37687
38087
  return JSON.stringify(errorResult, null, 2);
37688
38088
  }
37689
- const dirStat = fs8.statSync(scanDir);
38089
+ const dirStat = fs10.statSync(scanDir);
37690
38090
  if (!dirStat.isDirectory()) {
37691
38091
  const errorResult = {
37692
38092
  error: "target must be a directory, not a file",
@@ -37737,7 +38137,7 @@ var secretscan = createSwarmTool({
37737
38137
  break;
37738
38138
  const fileFindings = scanFileForSecrets(filePath);
37739
38139
  try {
37740
- const stat2 = fs8.statSync(filePath);
38140
+ const stat2 = fs10.statSync(filePath);
37741
38141
  if (stat2.size > MAX_FILE_SIZE_BYTES) {
37742
38142
  skippedFiles++;
37743
38143
  continue;
@@ -37824,12 +38224,12 @@ async function runSecretscan(directory) {
37824
38224
  }
37825
38225
 
37826
38226
  // src/tools/test-runner.ts
37827
- import * as fs10 from "fs";
37828
- import * as path20 from "path";
38227
+ import * as fs12 from "fs";
38228
+ import * as path22 from "path";
37829
38229
 
37830
38230
  // src/tools/resolve-working-directory.ts
37831
- import * as fs9 from "fs";
37832
- import * as path19 from "path";
38231
+ import * as fs11 from "fs";
38232
+ import * as path21 from "path";
37833
38233
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
37834
38234
  if (workingDirectory == null || workingDirectory === "") {
37835
38235
  return { success: true, directory: fallbackDirectory };
@@ -37849,17 +38249,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
37849
38249
  };
37850
38250
  }
37851
38251
  }
37852
- const normalizedDir = path19.normalize(workingDirectory);
37853
- const pathParts = normalizedDir.split(path19.sep);
38252
+ const normalizedDir = path21.normalize(workingDirectory);
38253
+ const pathParts = normalizedDir.split(path21.sep);
37854
38254
  if (pathParts.includes("..")) {
37855
38255
  return {
37856
38256
  success: false,
37857
38257
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
37858
38258
  };
37859
38259
  }
37860
- const resolvedDir = path19.resolve(normalizedDir);
38260
+ const resolvedDir = path21.resolve(normalizedDir);
37861
38261
  try {
37862
- const realPath = fs9.realpathSync(resolvedDir);
38262
+ const realPath = fs11.realpathSync(resolvedDir);
37863
38263
  return { success: true, directory: realPath };
37864
38264
  } catch {
37865
38265
  return {
@@ -37940,19 +38340,19 @@ function hasDevDependency(devDeps, ...patterns) {
37940
38340
  return hasPackageJsonDependency(devDeps, ...patterns);
37941
38341
  }
37942
38342
  function detectGoTest(cwd) {
37943
- return fs10.existsSync(path20.join(cwd, "go.mod")) && isCommandAvailable("go");
38343
+ return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("go");
37944
38344
  }
37945
38345
  function detectJavaMaven(cwd) {
37946
- return fs10.existsSync(path20.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38346
+ return fs12.existsSync(path22.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
37947
38347
  }
37948
38348
  function detectGradle(cwd) {
37949
- const hasBuildFile = fs10.existsSync(path20.join(cwd, "build.gradle")) || fs10.existsSync(path20.join(cwd, "build.gradle.kts"));
37950
- 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"));
37951
38351
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
37952
38352
  }
37953
38353
  function detectDotnetTest(cwd) {
37954
38354
  try {
37955
- const files = fs10.readdirSync(cwd);
38355
+ const files = fs12.readdirSync(cwd);
37956
38356
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
37957
38357
  return hasCsproj && isCommandAvailable("dotnet");
37958
38358
  } catch {
@@ -37960,32 +38360,32 @@ function detectDotnetTest(cwd) {
37960
38360
  }
37961
38361
  }
37962
38362
  function detectCTest(cwd) {
37963
- const hasSource = fs10.existsSync(path20.join(cwd, "CMakeLists.txt"));
37964
- 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"));
37965
38365
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
37966
38366
  }
37967
38367
  function detectSwiftTest(cwd) {
37968
- return fs10.existsSync(path20.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38368
+ return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swift");
37969
38369
  }
37970
38370
  function detectDartTest(cwd) {
37971
- 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"));
37972
38372
  }
37973
38373
  function detectRSpec(cwd) {
37974
- const hasRSpecFile = fs10.existsSync(path20.join(cwd, ".rspec"));
37975
- const hasGemfile = fs10.existsSync(path20.join(cwd, "Gemfile"));
37976
- 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"));
37977
38377
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
37978
38378
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
37979
38379
  }
37980
38380
  function detectMinitest(cwd) {
37981
- 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");
37982
38382
  }
37983
38383
  async function detectTestFramework(cwd) {
37984
38384
  const baseDir = cwd;
37985
38385
  try {
37986
- const packageJsonPath = path20.join(baseDir, "package.json");
37987
- if (fs10.existsSync(packageJsonPath)) {
37988
- 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");
37989
38389
  const pkg = JSON.parse(content);
37990
38390
  const _deps = pkg.dependencies || {};
37991
38391
  const devDeps = pkg.devDependencies || {};
@@ -38004,38 +38404,38 @@ async function detectTestFramework(cwd) {
38004
38404
  return "jest";
38005
38405
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
38006
38406
  return "mocha";
38007
- 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"))) {
38008
38408
  if (scripts.test?.includes("bun"))
38009
38409
  return "bun";
38010
38410
  }
38011
38411
  }
38012
38412
  } catch {}
38013
38413
  try {
38014
- const pyprojectTomlPath = path20.join(baseDir, "pyproject.toml");
38015
- const setupCfgPath = path20.join(baseDir, "setup.cfg");
38016
- const requirementsTxtPath = path20.join(baseDir, "requirements.txt");
38017
- if (fs10.existsSync(pyprojectTomlPath)) {
38018
- 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");
38019
38419
  if (content.includes("[tool.pytest"))
38020
38420
  return "pytest";
38021
38421
  if (content.includes("pytest"))
38022
38422
  return "pytest";
38023
38423
  }
38024
- if (fs10.existsSync(setupCfgPath)) {
38025
- const content = fs10.readFileSync(setupCfgPath, "utf-8");
38424
+ if (fs12.existsSync(setupCfgPath)) {
38425
+ const content = fs12.readFileSync(setupCfgPath, "utf-8");
38026
38426
  if (content.includes("[pytest]"))
38027
38427
  return "pytest";
38028
38428
  }
38029
- if (fs10.existsSync(requirementsTxtPath)) {
38030
- const content = fs10.readFileSync(requirementsTxtPath, "utf-8");
38429
+ if (fs12.existsSync(requirementsTxtPath)) {
38430
+ const content = fs12.readFileSync(requirementsTxtPath, "utf-8");
38031
38431
  if (content.includes("pytest"))
38032
38432
  return "pytest";
38033
38433
  }
38034
38434
  } catch {}
38035
38435
  try {
38036
- const cargoTomlPath = path20.join(baseDir, "Cargo.toml");
38037
- if (fs10.existsSync(cargoTomlPath)) {
38038
- 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");
38039
38439
  if (content.includes("[dev-dependencies]")) {
38040
38440
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
38041
38441
  return "cargo";
@@ -38044,10 +38444,10 @@ async function detectTestFramework(cwd) {
38044
38444
  }
38045
38445
  } catch {}
38046
38446
  try {
38047
- const pesterConfigPath = path20.join(baseDir, "pester.config.ps1");
38048
- const pesterConfigJsonPath = path20.join(baseDir, "pester.config.ps1.json");
38049
- const pesterPs1Path = path20.join(baseDir, "tests.ps1");
38050
- 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)) {
38051
38451
  return "pester";
38052
38452
  }
38053
38453
  } catch {}
@@ -38098,8 +38498,8 @@ function getTestFilesFromConvention(sourceFiles) {
38098
38498
  const testFiles = [];
38099
38499
  for (const file3 of sourceFiles) {
38100
38500
  const normalizedPath = file3.replace(/\\/g, "/");
38101
- const basename4 = path20.basename(file3);
38102
- const dirname9 = path20.dirname(file3);
38501
+ const basename4 = path22.basename(file3);
38502
+ const dirname9 = path22.dirname(file3);
38103
38503
  if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
38104
38504
  if (!testFiles.includes(file3)) {
38105
38505
  testFiles.push(file3);
@@ -38108,16 +38508,16 @@ function getTestFilesFromConvention(sourceFiles) {
38108
38508
  }
38109
38509
  for (const _pattern of TEST_PATTERNS) {
38110
38510
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
38111
- const ext = path20.extname(basename4);
38511
+ const ext = path22.extname(basename4);
38112
38512
  const possibleTestFiles = [
38113
- path20.join(dirname9, `${nameWithoutExt}.spec${ext}`),
38114
- path20.join(dirname9, `${nameWithoutExt}.test${ext}`),
38115
- path20.join(dirname9, "__tests__", `${nameWithoutExt}${ext}`),
38116
- path20.join(dirname9, "tests", `${nameWithoutExt}${ext}`),
38117
- 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}`)
38118
38518
  ];
38119
38519
  for (const testFile of possibleTestFiles) {
38120
- if (fs10.existsSync(testFile) && !testFiles.includes(testFile)) {
38520
+ if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
38121
38521
  testFiles.push(testFile);
38122
38522
  }
38123
38523
  }
@@ -38133,8 +38533,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38133
38533
  }
38134
38534
  for (const testFile of candidateTestFiles) {
38135
38535
  try {
38136
- const content = fs10.readFileSync(testFile, "utf-8");
38137
- const testDir = path20.dirname(testFile);
38536
+ const content = fs12.readFileSync(testFile, "utf-8");
38537
+ const testDir = path22.dirname(testFile);
38138
38538
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
38139
38539
  let match;
38140
38540
  match = importRegex.exec(content);
@@ -38142,8 +38542,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38142
38542
  const importPath = match[1];
38143
38543
  let resolvedImport;
38144
38544
  if (importPath.startsWith(".")) {
38145
- resolvedImport = path20.resolve(testDir, importPath);
38146
- const existingExt = path20.extname(resolvedImport);
38545
+ resolvedImport = path22.resolve(testDir, importPath);
38546
+ const existingExt = path22.extname(resolvedImport);
38147
38547
  if (!existingExt) {
38148
38548
  for (const extToTry of [
38149
38549
  ".ts",
@@ -38154,7 +38554,7 @@ async function getTestFilesFromGraph(sourceFiles) {
38154
38554
  ".cjs"
38155
38555
  ]) {
38156
38556
  const withExt = resolvedImport + extToTry;
38157
- if (sourceFiles.includes(withExt) || fs10.existsSync(withExt)) {
38557
+ if (sourceFiles.includes(withExt) || fs12.existsSync(withExt)) {
38158
38558
  resolvedImport = withExt;
38159
38559
  break;
38160
38560
  }
@@ -38163,12 +38563,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38163
38563
  } else {
38164
38564
  continue;
38165
38565
  }
38166
- const importBasename = path20.basename(resolvedImport, path20.extname(resolvedImport));
38167
- const importDir = path20.dirname(resolvedImport);
38566
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38567
+ const importDir = path22.dirname(resolvedImport);
38168
38568
  for (const sourceFile of sourceFiles) {
38169
- const sourceDir = path20.dirname(sourceFile);
38170
- const sourceBasename = path20.basename(sourceFile, path20.extname(sourceFile));
38171
- 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");
38172
38572
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38173
38573
  if (!testFiles.includes(testFile)) {
38174
38574
  testFiles.push(testFile);
@@ -38183,8 +38583,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38183
38583
  while (match !== null) {
38184
38584
  const importPath = match[1];
38185
38585
  if (importPath.startsWith(".")) {
38186
- let resolvedImport = path20.resolve(testDir, importPath);
38187
- const existingExt = path20.extname(resolvedImport);
38586
+ let resolvedImport = path22.resolve(testDir, importPath);
38587
+ const existingExt = path22.extname(resolvedImport);
38188
38588
  if (!existingExt) {
38189
38589
  for (const extToTry of [
38190
38590
  ".ts",
@@ -38195,18 +38595,18 @@ async function getTestFilesFromGraph(sourceFiles) {
38195
38595
  ".cjs"
38196
38596
  ]) {
38197
38597
  const withExt = resolvedImport + extToTry;
38198
- if (sourceFiles.includes(withExt) || fs10.existsSync(withExt)) {
38598
+ if (sourceFiles.includes(withExt) || fs12.existsSync(withExt)) {
38199
38599
  resolvedImport = withExt;
38200
38600
  break;
38201
38601
  }
38202
38602
  }
38203
38603
  }
38204
- const importDir = path20.dirname(resolvedImport);
38205
- const importBasename = path20.basename(resolvedImport, path20.extname(resolvedImport));
38604
+ const importDir = path22.dirname(resolvedImport);
38605
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38206
38606
  for (const sourceFile of sourceFiles) {
38207
- const sourceDir = path20.dirname(sourceFile);
38208
- const sourceBasename = path20.basename(sourceFile, path20.extname(sourceFile));
38209
- 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");
38210
38610
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38211
38611
  if (!testFiles.includes(testFile)) {
38212
38612
  testFiles.push(testFile);
@@ -38291,8 +38691,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38291
38691
  return ["mvn", "test"];
38292
38692
  case "gradle": {
38293
38693
  const isWindows = process.platform === "win32";
38294
- const hasGradlewBat = fs10.existsSync(path20.join(baseDir, "gradlew.bat"));
38295
- 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"));
38296
38696
  if (hasGradlewBat && isWindows)
38297
38697
  return ["gradlew.bat", "test"];
38298
38698
  if (hasGradlew)
@@ -38309,7 +38709,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38309
38709
  "cmake-build-release",
38310
38710
  "out"
38311
38711
  ];
38312
- 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";
38313
38713
  return ["ctest", "--test-dir", actualBuildDir];
38314
38714
  }
38315
38715
  case "swift-test":
@@ -38851,7 +39251,7 @@ var test_runner = createSwarmTool({
38851
39251
  let effectiveScope = scope;
38852
39252
  if (scope === "all") {} else if (scope === "convention") {
38853
39253
  const sourceFiles = args.files.filter((f) => {
38854
- const ext = path20.extname(f).toLowerCase();
39254
+ const ext = path22.extname(f).toLowerCase();
38855
39255
  return SOURCE_EXTENSIONS.has(ext);
38856
39256
  });
38857
39257
  if (sourceFiles.length === 0) {
@@ -38867,7 +39267,7 @@ var test_runner = createSwarmTool({
38867
39267
  testFiles = getTestFilesFromConvention(sourceFiles);
38868
39268
  } else if (scope === "graph") {
38869
39269
  const sourceFiles = args.files.filter((f) => {
38870
- const ext = path20.extname(f).toLowerCase();
39270
+ const ext = path22.extname(f).toLowerCase();
38871
39271
  return SOURCE_EXTENSIONS.has(ext);
38872
39272
  });
38873
39273
  if (sourceFiles.length === 0) {
@@ -38938,8 +39338,8 @@ function validateDirectoryPath(dir) {
38938
39338
  if (dir.includes("..")) {
38939
39339
  throw new Error("Directory path must not contain path traversal sequences");
38940
39340
  }
38941
- const normalized = path21.normalize(dir);
38942
- 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);
38943
39343
  return absolutePath;
38944
39344
  }
38945
39345
  function validateTimeout(timeoutMs, defaultValue) {
@@ -38962,9 +39362,9 @@ function validateTimeout(timeoutMs, defaultValue) {
38962
39362
  }
38963
39363
  function getPackageVersion(dir) {
38964
39364
  try {
38965
- const packagePath = path21.join(dir, "package.json");
38966
- if (fs11.existsSync(packagePath)) {
38967
- 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");
38968
39368
  const pkg = JSON.parse(content);
38969
39369
  return pkg.version ?? null;
38970
39370
  }
@@ -38973,9 +39373,9 @@ function getPackageVersion(dir) {
38973
39373
  }
38974
39374
  function getChangelogVersion(dir) {
38975
39375
  try {
38976
- const changelogPath = path21.join(dir, "CHANGELOG.md");
38977
- if (fs11.existsSync(changelogPath)) {
38978
- 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");
38979
39379
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
38980
39380
  if (match) {
38981
39381
  return match[1];
@@ -38987,10 +39387,10 @@ function getChangelogVersion(dir) {
38987
39387
  function getVersionFileVersion(dir) {
38988
39388
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
38989
39389
  for (const file3 of possibleFiles) {
38990
- const filePath = path21.join(dir, file3);
38991
- if (fs11.existsSync(filePath)) {
39390
+ const filePath = path23.join(dir, file3);
39391
+ if (fs13.existsSync(filePath)) {
38992
39392
  try {
38993
- const content = fs11.readFileSync(filePath, "utf-8").trim();
39393
+ const content = fs13.readFileSync(filePath, "utf-8").trim();
38994
39394
  const match = content.match(/(\d+\.\d+\.\d+)/);
38995
39395
  if (match) {
38996
39396
  return match[1];
@@ -39534,7 +39934,7 @@ async function handlePromoteCommand(directory, args) {
39534
39934
  }
39535
39935
 
39536
39936
  // src/commands/reset.ts
39537
- import * as fs12 from "fs";
39937
+ import * as fs14 from "fs";
39538
39938
 
39539
39939
  // src/background/manager.ts
39540
39940
  init_utils();
@@ -40235,8 +40635,8 @@ async function handleResetCommand(directory, args) {
40235
40635
  for (const filename of filesToReset) {
40236
40636
  try {
40237
40637
  const resolvedPath = validateSwarmPath(directory, filename);
40238
- if (fs12.existsSync(resolvedPath)) {
40239
- fs12.unlinkSync(resolvedPath);
40638
+ if (fs14.existsSync(resolvedPath)) {
40639
+ fs14.unlinkSync(resolvedPath);
40240
40640
  results.push(`- \u2705 Deleted ${filename}`);
40241
40641
  } else {
40242
40642
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -40253,8 +40653,8 @@ async function handleResetCommand(directory, args) {
40253
40653
  }
40254
40654
  try {
40255
40655
  const summariesPath = validateSwarmPath(directory, "summaries");
40256
- if (fs12.existsSync(summariesPath)) {
40257
- fs12.rmSync(summariesPath, { recursive: true, force: true });
40656
+ if (fs14.existsSync(summariesPath)) {
40657
+ fs14.rmSync(summariesPath, { recursive: true, force: true });
40258
40658
  results.push("- \u2705 Deleted summaries/ directory");
40259
40659
  } else {
40260
40660
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -40274,14 +40674,14 @@ async function handleResetCommand(directory, args) {
40274
40674
 
40275
40675
  // src/commands/reset-session.ts
40276
40676
  init_utils2();
40277
- import * as fs13 from "fs";
40278
- import * as path22 from "path";
40677
+ import * as fs15 from "fs";
40678
+ import * as path24 from "path";
40279
40679
  async function handleResetSessionCommand(directory, _args) {
40280
40680
  const results = [];
40281
40681
  try {
40282
40682
  const statePath = validateSwarmPath(directory, "session/state.json");
40283
- if (fs13.existsSync(statePath)) {
40284
- fs13.unlinkSync(statePath);
40683
+ if (fs15.existsSync(statePath)) {
40684
+ fs15.unlinkSync(statePath);
40285
40685
  results.push("\u2705 Deleted .swarm/session/state.json");
40286
40686
  } else {
40287
40687
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -40290,15 +40690,15 @@ async function handleResetSessionCommand(directory, _args) {
40290
40690
  results.push("\u274C Failed to delete state.json");
40291
40691
  }
40292
40692
  try {
40293
- const sessionDir = path22.dirname(validateSwarmPath(directory, "session/state.json"));
40294
- if (fs13.existsSync(sessionDir)) {
40295
- 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);
40296
40696
  const otherFiles = files.filter((f) => f !== "state.json");
40297
40697
  let deletedCount = 0;
40298
40698
  for (const file3 of otherFiles) {
40299
- const filePath = path22.join(sessionDir, file3);
40300
- if (fs13.lstatSync(filePath).isFile()) {
40301
- fs13.unlinkSync(filePath);
40699
+ const filePath = path24.join(sessionDir, file3);
40700
+ if (fs15.lstatSync(filePath).isFile()) {
40701
+ fs15.unlinkSync(filePath);
40302
40702
  deletedCount++;
40303
40703
  }
40304
40704
  }
@@ -40326,7 +40726,7 @@ async function handleResetSessionCommand(directory, _args) {
40326
40726
  // src/summaries/manager.ts
40327
40727
  init_utils2();
40328
40728
  init_utils();
40329
- import * as path23 from "path";
40729
+ import * as path25 from "path";
40330
40730
  var SUMMARY_ID_REGEX = /^S\d+$/;
40331
40731
  function sanitizeSummaryId(id) {
40332
40732
  if (!id || id.length === 0) {
@@ -40350,7 +40750,7 @@ function sanitizeSummaryId(id) {
40350
40750
  }
40351
40751
  async function loadFullOutput(directory, id) {
40352
40752
  const sanitizedId = sanitizeSummaryId(id);
40353
- const relativePath = path23.join("summaries", `${sanitizedId}.json`);
40753
+ const relativePath = path25.join("summaries", `${sanitizedId}.json`);
40354
40754
  validateSwarmPath(directory, relativePath);
40355
40755
  const content = await readSwarmFileAsync(directory, relativePath);
40356
40756
  if (content === null) {
@@ -40403,18 +40803,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
40403
40803
 
40404
40804
  // src/commands/rollback.ts
40405
40805
  init_utils2();
40406
- import * as fs14 from "fs";
40407
- import * as path24 from "path";
40806
+ import * as fs16 from "fs";
40807
+ import * as path26 from "path";
40408
40808
  async function handleRollbackCommand(directory, args) {
40409
40809
  const phaseArg = args[0];
40410
40810
  if (!phaseArg) {
40411
40811
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
40412
- if (!fs14.existsSync(manifestPath2)) {
40812
+ if (!fs16.existsSync(manifestPath2)) {
40413
40813
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
40414
40814
  }
40415
40815
  let manifest2;
40416
40816
  try {
40417
- manifest2 = JSON.parse(fs14.readFileSync(manifestPath2, "utf-8"));
40817
+ manifest2 = JSON.parse(fs16.readFileSync(manifestPath2, "utf-8"));
40418
40818
  } catch {
40419
40819
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
40420
40820
  }
@@ -40436,12 +40836,12 @@ async function handleRollbackCommand(directory, args) {
40436
40836
  return "Error: Phase number must be a positive integer.";
40437
40837
  }
40438
40838
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
40439
- if (!fs14.existsSync(manifestPath)) {
40839
+ if (!fs16.existsSync(manifestPath)) {
40440
40840
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
40441
40841
  }
40442
40842
  let manifest;
40443
40843
  try {
40444
- manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf-8"));
40844
+ manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf-8"));
40445
40845
  } catch {
40446
40846
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
40447
40847
  }
@@ -40451,10 +40851,10 @@ async function handleRollbackCommand(directory, args) {
40451
40851
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
40452
40852
  }
40453
40853
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
40454
- if (!fs14.existsSync(checkpointDir)) {
40854
+ if (!fs16.existsSync(checkpointDir)) {
40455
40855
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
40456
40856
  }
40457
- const checkpointFiles = fs14.readdirSync(checkpointDir);
40857
+ const checkpointFiles = fs16.readdirSync(checkpointDir);
40458
40858
  if (checkpointFiles.length === 0) {
40459
40859
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
40460
40860
  }
@@ -40462,10 +40862,10 @@ async function handleRollbackCommand(directory, args) {
40462
40862
  const successes = [];
40463
40863
  const failures = [];
40464
40864
  for (const file3 of checkpointFiles) {
40465
- const src = path24.join(checkpointDir, file3);
40466
- const dest = path24.join(swarmDir, file3);
40865
+ const src = path26.join(checkpointDir, file3);
40866
+ const dest = path26.join(swarmDir, file3);
40467
40867
  try {
40468
- fs14.cpSync(src, dest, { recursive: true, force: true });
40868
+ fs16.cpSync(src, dest, { recursive: true, force: true });
40469
40869
  successes.push(file3);
40470
40870
  } catch (error93) {
40471
40871
  failures.push({ file: file3, error: error93.message });
@@ -40482,7 +40882,7 @@ async function handleRollbackCommand(directory, args) {
40482
40882
  timestamp: new Date().toISOString()
40483
40883
  };
40484
40884
  try {
40485
- fs14.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40885
+ fs16.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40486
40886
  `);
40487
40887
  } catch (error93) {
40488
40888
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -40525,11 +40925,11 @@ async function handleSimulateCommand(directory, args) {
40525
40925
  ];
40526
40926
  const report = reportLines.filter(Boolean).join(`
40527
40927
  `);
40528
- const fs15 = await import("fs/promises");
40529
- const path25 = await import("path");
40530
- const reportPath = path25.join(directory, ".swarm", "simulate-report.md");
40531
- await fs15.mkdir(path25.dirname(reportPath), { recursive: true });
40532
- 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");
40533
40933
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
40534
40934
  }
40535
40935
 
@@ -41011,18 +41411,18 @@ function resolveCommand(tokens) {
41011
41411
  }
41012
41412
 
41013
41413
  // src/cli/index.ts
41014
- var CONFIG_DIR = path25.join(process.env.XDG_CONFIG_HOME || path25.join(os5.homedir(), ".config"), "opencode");
41015
- var OPENCODE_CONFIG_PATH = path25.join(CONFIG_DIR, "opencode.json");
41016
- var PLUGIN_CONFIG_PATH = path25.join(CONFIG_DIR, "opencode-swarm.json");
41017
- 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");
41018
41418
  function ensureDir(dir) {
41019
- if (!fs15.existsSync(dir)) {
41020
- fs15.mkdirSync(dir, { recursive: true });
41419
+ if (!fs17.existsSync(dir)) {
41420
+ fs17.mkdirSync(dir, { recursive: true });
41021
41421
  }
41022
41422
  }
41023
41423
  function loadJson(filepath) {
41024
41424
  try {
41025
- const content = fs15.readFileSync(filepath, "utf-8");
41425
+ const content = fs17.readFileSync(filepath, "utf-8");
41026
41426
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
41027
41427
  return JSON.parse(stripped);
41028
41428
  } catch {
@@ -41030,7 +41430,7 @@ function loadJson(filepath) {
41030
41430
  }
41031
41431
  }
41032
41432
  function saveJson(filepath, data) {
41033
- fs15.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41433
+ fs17.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41034
41434
  `, "utf-8");
41035
41435
  }
41036
41436
  async function install() {
@@ -41038,7 +41438,7 @@ async function install() {
41038
41438
  `);
41039
41439
  ensureDir(CONFIG_DIR);
41040
41440
  ensureDir(PROMPTS_DIR);
41041
- const LEGACY_CONFIG_PATH = path25.join(CONFIG_DIR, "config.json");
41441
+ const LEGACY_CONFIG_PATH = path27.join(CONFIG_DIR, "config.json");
41042
41442
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41043
41443
  if (!opencodeConfig) {
41044
41444
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -41063,7 +41463,7 @@ async function install() {
41063
41463
  saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
41064
41464
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
41065
41465
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
41066
- if (!fs15.existsSync(PLUGIN_CONFIG_PATH)) {
41466
+ if (!fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41067
41467
  const defaultConfig = {
41068
41468
  agents: {
41069
41469
  coder: { model: "opencode/minimax-m2.5-free" },
@@ -41106,7 +41506,7 @@ async function uninstall() {
41106
41506
  `);
41107
41507
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41108
41508
  if (!opencodeConfig) {
41109
- if (fs15.existsSync(OPENCODE_CONFIG_PATH)) {
41509
+ if (fs17.existsSync(OPENCODE_CONFIG_PATH)) {
41110
41510
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
41111
41511
  return 1;
41112
41512
  } else {
@@ -41138,13 +41538,13 @@ async function uninstall() {
41138
41538
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
41139
41539
  if (process.argv.includes("--clean")) {
41140
41540
  let cleaned = false;
41141
- if (fs15.existsSync(PLUGIN_CONFIG_PATH)) {
41142
- fs15.unlinkSync(PLUGIN_CONFIG_PATH);
41541
+ if (fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41542
+ fs17.unlinkSync(PLUGIN_CONFIG_PATH);
41143
41543
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
41144
41544
  cleaned = true;
41145
41545
  }
41146
- if (fs15.existsSync(PROMPTS_DIR)) {
41147
- fs15.rmSync(PROMPTS_DIR, { recursive: true });
41546
+ if (fs17.existsSync(PROMPTS_DIR)) {
41547
+ fs17.rmSync(PROMPTS_DIR, { recursive: true });
41148
41548
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
41149
41549
  cleaned = true;
41150
41550
  }