opencode-swarm 6.46.0 → 6.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -16046,20 +16046,22 @@ async function readLedgerEvents(directory) {
16046
16046
  return [];
16047
16047
  }
16048
16048
  }
16049
- async function initLedger(directory, planId) {
16049
+ async function initLedger(directory, planId, initialPlanHash) {
16050
16050
  const ledgerPath = getLedgerPath(directory);
16051
16051
  const planJsonPath = getPlanJsonPath(directory);
16052
16052
  if (fs6.existsSync(ledgerPath)) {
16053
16053
  throw new Error("Ledger already initialized. Use appendLedgerEvent to add events.");
16054
16054
  }
16055
- let planHashAfter = "";
16056
- try {
16057
- if (fs6.existsSync(planJsonPath)) {
16058
- const content = fs6.readFileSync(planJsonPath, "utf8");
16059
- const plan = JSON.parse(content);
16060
- planHashAfter = computePlanHash(plan);
16061
- }
16062
- } catch {}
16055
+ let planHashAfter = initialPlanHash ?? "";
16056
+ if (!initialPlanHash) {
16057
+ try {
16058
+ if (fs6.existsSync(planJsonPath)) {
16059
+ const content = fs6.readFileSync(planJsonPath, "utf8");
16060
+ const plan = JSON.parse(content);
16061
+ planHashAfter = computePlanHash(plan);
16062
+ }
16063
+ } catch {}
16064
+ }
16063
16065
  const event = {
16064
16066
  seq: 1,
16065
16067
  timestamp: new Date().toISOString(),
@@ -16071,7 +16073,7 @@ async function initLedger(directory, planId) {
16071
16073
  schema_version: LEDGER_SCHEMA_VERSION
16072
16074
  };
16073
16075
  fs6.mkdirSync(path6.join(directory, ".swarm"), { recursive: true });
16074
- const tempPath = `${ledgerPath}.tmp`;
16076
+ const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
16075
16077
  const line = `${JSON.stringify(event)}
16076
16078
  `;
16077
16079
  fs6.writeFileSync(tempPath, line, "utf8");
@@ -16098,7 +16100,7 @@ async function appendLedgerEvent(directory, eventInput, options) {
16098
16100
  schema_version: LEDGER_SCHEMA_VERSION
16099
16101
  };
16100
16102
  fs6.mkdirSync(path6.join(directory, ".swarm"), { recursive: true });
16101
- const tempPath = `${ledgerPath}.tmp`;
16103
+ const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
16102
16104
  const line = `${JSON.stringify(event)}
16103
16105
  `;
16104
16106
  if (fs6.existsSync(ledgerPath)) {
@@ -16116,10 +16118,11 @@ async function takeSnapshotEvent(directory, plan, options) {
16116
16118
  plan,
16117
16119
  payload_hash: payloadHash
16118
16120
  };
16121
+ const planId = `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16119
16122
  return appendLedgerEvent(directory, {
16120
16123
  event_type: "snapshot",
16121
16124
  source: "takeSnapshotEvent",
16122
- plan_id: plan.title,
16125
+ plan_id: planId,
16123
16126
  payload: snapshotPayload
16124
16127
  }, options);
16125
16128
  }
@@ -16128,13 +16131,15 @@ async function replayFromLedger(directory, options) {
16128
16131
  if (events.length === 0) {
16129
16132
  return null;
16130
16133
  }
16134
+ const targetPlanId = events[0].plan_id;
16135
+ const relevantEvents = events.filter((e) => e.plan_id === targetPlanId);
16131
16136
  {
16132
- const snapshotEvents = events.filter((e) => e.event_type === "snapshot");
16137
+ const snapshotEvents = relevantEvents.filter((e) => e.event_type === "snapshot");
16133
16138
  if (snapshotEvents.length > 0) {
16134
16139
  const latestSnapshotEvent = snapshotEvents[snapshotEvents.length - 1];
16135
16140
  const snapshotPayload = latestSnapshotEvent.payload;
16136
16141
  let plan2 = snapshotPayload.plan;
16137
- const eventsAfterSnapshot = events.filter((e) => e.seq > latestSnapshotEvent.seq);
16142
+ const eventsAfterSnapshot = relevantEvents.filter((e) => e.seq > latestSnapshotEvent.seq);
16138
16143
  for (const event of eventsAfterSnapshot) {
16139
16144
  plan2 = applyEventToPlan(plan2, event);
16140
16145
  if (plan2 === null) {
@@ -16155,7 +16160,7 @@ async function replayFromLedger(directory, options) {
16155
16160
  } catch {
16156
16161
  return null;
16157
16162
  }
16158
- for (const event of events) {
16163
+ for (const event of relevantEvents) {
16159
16164
  if (plan === null) {
16160
16165
  return null;
16161
16166
  }
@@ -16169,10 +16174,14 @@ function applyEventToPlan(plan, event) {
16169
16174
  return plan;
16170
16175
  case "task_status_changed":
16171
16176
  if (event.task_id && event.to_status) {
16177
+ const parseResult = TaskStatusSchema.safeParse(event.to_status);
16178
+ if (!parseResult.success) {
16179
+ return plan;
16180
+ }
16172
16181
  for (const phase of plan.phases) {
16173
16182
  const task = phase.tasks.find((t) => t.id === event.task_id);
16174
16183
  if (task) {
16175
- task.status = event.to_status;
16184
+ task.status = parseResult.data;
16176
16185
  break;
16177
16186
  }
16178
16187
  }
@@ -16206,6 +16215,7 @@ function applyEventToPlan(plan, event) {
16206
16215
  }
16207
16216
  var LEDGER_SCHEMA_VERSION = "1.0.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
16208
16217
  var init_ledger = __esm(() => {
16218
+ init_plan_schema();
16209
16219
  LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
16210
16220
  constructor(message) {
16211
16221
  super(message);
@@ -16215,7 +16225,7 @@ var init_ledger = __esm(() => {
16215
16225
  });
16216
16226
 
16217
16227
  // src/plan/manager.ts
16218
- import { renameSync as renameSync3, unlinkSync } from "fs";
16228
+ import { existsSync as existsSync4, renameSync as renameSync3, unlinkSync } from "fs";
16219
16229
  import * as path7 from "path";
16220
16230
  async function loadPlanJsonOnly(directory) {
16221
16231
  const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
@@ -16346,28 +16356,49 @@ async function loadPlan(directory) {
16346
16356
  const planHash = computePlanHash(validated);
16347
16357
  const ledgerHash = await getLatestLedgerHash(directory);
16348
16358
  if (ledgerHash !== "" && planHash !== ledgerHash) {
16349
- 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.");
16350
- try {
16351
- const rebuilt = await replayFromLedger(directory);
16352
- if (rebuilt) {
16353
- await rebuildPlan(directory, rebuilt);
16354
- warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at SWARM_PLAN.md if it exists.");
16355
- return rebuilt;
16359
+ const currentPlanId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16360
+ const ledgerEvents = await readLedgerEvents(directory);
16361
+ const firstEvent = ledgerEvents.length > 0 ? ledgerEvents[0] : null;
16362
+ if (firstEvent && firstEvent.plan_id !== currentPlanId) {
16363
+ warn(`[loadPlan] Ledger identity mismatch (ledger: ${firstEvent.plan_id}, plan: ${currentPlanId}) \u2014 skipping ledger rebuild (migration detected). Use /swarm reset-session to reinitialize the ledger.`);
16364
+ } else {
16365
+ 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.");
16366
+ try {
16367
+ const rebuilt = await replayFromLedger(directory);
16368
+ if (rebuilt) {
16369
+ await rebuildPlan(directory, rebuilt);
16370
+ warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at SWARM_PLAN.md if it exists.");
16371
+ return rebuilt;
16372
+ }
16373
+ } catch (replayError) {
16374
+ 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.`);
16356
16375
  }
16357
- } catch (replayError) {
16358
- 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.`);
16359
16376
  }
16360
16377
  }
16361
16378
  }
16362
16379
  return validated;
16363
16380
  } catch (error49) {
16364
16381
  warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error ? error49.message : String(error49)}. Attempting rebuild from ledger. If rebuild fails, check SWARM_PLAN.md for a checkpoint.`);
16382
+ let rawPlanId = null;
16383
+ try {
16384
+ const rawParsed = JSON.parse(planJsonContent);
16385
+ if (typeof rawParsed?.swarm === "string" && typeof rawParsed?.title === "string") {
16386
+ rawPlanId = `${rawParsed.swarm}-${rawParsed.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16387
+ }
16388
+ } catch {}
16365
16389
  if (await ledgerExists(directory)) {
16366
- const rebuilt = await replayFromLedger(directory);
16367
- if (rebuilt) {
16368
- await rebuildPlan(directory, rebuilt);
16369
- warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale.");
16370
- return rebuilt;
16390
+ const ledgerEventsForCatch = await readLedgerEvents(directory);
16391
+ const catchFirstEvent = ledgerEventsForCatch.length > 0 ? ledgerEventsForCatch[0] : null;
16392
+ const identityMatch = rawPlanId === null || catchFirstEvent === null || catchFirstEvent.plan_id === rawPlanId;
16393
+ if (!identityMatch) {
16394
+ warn(`[loadPlan] Ledger identity mismatch in validation-failure path (ledger: ${catchFirstEvent?.plan_id}, plan: ${rawPlanId}) \u2014 skipping ledger rebuild (migration detected).`);
16395
+ } else if (catchFirstEvent !== null && rawPlanId !== null) {
16396
+ const rebuilt = await replayFromLedger(directory);
16397
+ if (rebuilt) {
16398
+ await rebuildPlan(directory, rebuilt);
16399
+ warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale.");
16400
+ return rebuilt;
16401
+ }
16371
16402
  }
16372
16403
  }
16373
16404
  const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
@@ -16435,9 +16466,28 @@ async function savePlan(directory, plan, options) {
16435
16466
  }
16436
16467
  }
16437
16468
  const currentPlan = await loadPlanJsonOnly(directory);
16469
+ const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16470
+ const planHashForInit = computePlanHash(validated);
16438
16471
  if (!await ledgerExists(directory)) {
16439
- const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
16440
- await initLedger(directory, planId);
16472
+ await initLedger(directory, planId, planHashForInit);
16473
+ } else {
16474
+ const existingEvents = await readLedgerEvents(directory);
16475
+ if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
16476
+ const swarmDir2 = path7.resolve(directory, ".swarm");
16477
+ const oldLedgerPath = path7.join(swarmDir2, "plan-ledger.jsonl");
16478
+ const archivePath = path7.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
16479
+ if (existsSync4(oldLedgerPath)) {
16480
+ renameSync3(oldLedgerPath, archivePath);
16481
+ warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") \u2014 archived old ledger to ${archivePath} and reinitializing.`);
16482
+ }
16483
+ try {
16484
+ await initLedger(directory, planId, planHashForInit);
16485
+ } catch (initErr) {
16486
+ if (!(initErr instanceof Error && initErr.message.includes("already initialized"))) {
16487
+ throw initErr;
16488
+ }
16489
+ }
16490
+ }
16441
16491
  }
16442
16492
  const currentHash = computeCurrentPlanHash(directory);
16443
16493
  const hashAfter = computePlanHash(validated);
@@ -16530,10 +16580,24 @@ async function rebuildPlan(directory, plan) {
16530
16580
  const tempPlanPath = path7.join(swarmDir, `plan.json.rebuild.${Date.now()}`);
16531
16581
  await Bun.write(tempPlanPath, JSON.stringify(targetPlan, null, 2));
16532
16582
  renameSync3(tempPlanPath, planPath);
16583
+ const contentHash = computePlanContentHash(targetPlan);
16533
16584
  const markdown = derivePlanMarkdown(targetPlan);
16585
+ const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16586
+ ${markdown}`;
16534
16587
  const tempMdPath = path7.join(swarmDir, `plan.md.rebuild.${Date.now()}`);
16535
- await Bun.write(tempMdPath, markdown);
16588
+ await Bun.write(tempMdPath, markdownWithHash);
16536
16589
  renameSync3(tempMdPath, mdPath);
16590
+ try {
16591
+ const markerPath = path7.join(swarmDir, ".plan-write-marker");
16592
+ const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
16593
+ const marker = JSON.stringify({
16594
+ source: "plan_manager",
16595
+ timestamp: new Date().toISOString(),
16596
+ phases_count: targetPlan.phases.length,
16597
+ tasks_count: tasksCount
16598
+ });
16599
+ await Bun.write(markerPath, marker);
16600
+ } catch {}
16537
16601
  return targetPlan;
16538
16602
  }
16539
16603
  async function updateTaskStatus(directory, taskId, status) {
@@ -17134,11 +17198,11 @@ __export(exports_evidence_summary_integration, {
17134
17198
  createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
17135
17199
  EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
17136
17200
  });
17137
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, writeFileSync as writeFileSync2 } from "fs";
17201
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync2 } from "fs";
17138
17202
  import * as path8 from "path";
17139
17203
  function persistSummary(swarmDir, artifact, filename) {
17140
17204
  const swarmPath = path8.join(swarmDir, ".swarm");
17141
- if (!existsSync4(swarmPath)) {
17205
+ if (!existsSync5(swarmPath)) {
17142
17206
  mkdirSync4(swarmPath, { recursive: true });
17143
17207
  }
17144
17208
  const artifactPath = path8.join(swarmPath, filename);
@@ -32356,7 +32420,7 @@ var require_proper_lockfile = __commonJS((exports, module2) => {
32356
32420
  });
32357
32421
 
32358
32422
  // src/hooks/knowledge-store.ts
32359
- import { existsSync as existsSync8 } from "fs";
32423
+ import { existsSync as existsSync9 } from "fs";
32360
32424
  import { appendFile, mkdir, readFile as readFile2, writeFile } from "fs/promises";
32361
32425
  import * as os3 from "os";
32362
32426
  import * as path12 from "path";
@@ -32384,7 +32448,7 @@ function resolveHiveRejectedPath() {
32384
32448
  return path12.join(path12.dirname(hivePath), "shared-learnings-rejected.jsonl");
32385
32449
  }
32386
32450
  async function readKnowledge(filePath) {
32387
- if (!existsSync8(filePath))
32451
+ if (!existsSync9(filePath))
32388
32452
  return [];
32389
32453
  const content = await readFile2(filePath, "utf-8");
32390
32454
  const results = [];
@@ -32533,7 +32597,7 @@ __export(exports_co_change_analyzer, {
32533
32597
  import * as child_process2 from "child_process";
32534
32598
  import { randomUUID as randomUUID2 } from "crypto";
32535
32599
  import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
32536
- import * as path19 from "path";
32600
+ import * as path20 from "path";
32537
32601
  import { promisify } from "util";
32538
32602
  function getExecFileAsync() {
32539
32603
  return promisify(child_process2.execFile);
@@ -32635,7 +32699,7 @@ async function scanSourceFiles(dir) {
32635
32699
  try {
32636
32700
  const entries = await readdir2(dir, { withFileTypes: true });
32637
32701
  for (const entry of entries) {
32638
- const fullPath = path19.join(dir, entry.name);
32702
+ const fullPath = path20.join(dir, entry.name);
32639
32703
  if (entry.isDirectory()) {
32640
32704
  if (skipDirs.has(entry.name)) {
32641
32705
  continue;
@@ -32643,7 +32707,7 @@ async function scanSourceFiles(dir) {
32643
32707
  const subFiles = await scanSourceFiles(fullPath);
32644
32708
  results.push(...subFiles);
32645
32709
  } else if (entry.isFile()) {
32646
- const ext = path19.extname(entry.name);
32710
+ const ext = path20.extname(entry.name);
32647
32711
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
32648
32712
  results.push(fullPath);
32649
32713
  }
@@ -32665,8 +32729,8 @@ async function getStaticEdges(directory) {
32665
32729
  continue;
32666
32730
  }
32667
32731
  try {
32668
- const sourceDir = path19.dirname(sourceFile);
32669
- const resolvedPath = path19.resolve(sourceDir, importPath);
32732
+ const sourceDir = path20.dirname(sourceFile);
32733
+ const resolvedPath = path20.resolve(sourceDir, importPath);
32670
32734
  const extensions = [
32671
32735
  "",
32672
32736
  ".ts",
@@ -32691,8 +32755,8 @@ async function getStaticEdges(directory) {
32691
32755
  if (!targetFile) {
32692
32756
  continue;
32693
32757
  }
32694
- const relSource = path19.relative(directory, sourceFile).replace(/\\/g, "/");
32695
- const relTarget = path19.relative(directory, targetFile).replace(/\\/g, "/");
32758
+ const relSource = path20.relative(directory, sourceFile).replace(/\\/g, "/");
32759
+ const relTarget = path20.relative(directory, targetFile).replace(/\\/g, "/");
32696
32760
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
32697
32761
  edges.add(key);
32698
32762
  } catch {}
@@ -32704,7 +32768,7 @@ async function getStaticEdges(directory) {
32704
32768
  function isTestImplementationPair(fileA, fileB) {
32705
32769
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
32706
32770
  const getBaseName = (filePath) => {
32707
- const base = path19.basename(filePath);
32771
+ const base = path20.basename(filePath);
32708
32772
  for (const pattern of testPatterns) {
32709
32773
  if (base.endsWith(pattern)) {
32710
32774
  return base.slice(0, -pattern.length);
@@ -32714,16 +32778,16 @@ function isTestImplementationPair(fileA, fileB) {
32714
32778
  };
32715
32779
  const baseA = getBaseName(fileA);
32716
32780
  const baseB = getBaseName(fileB);
32717
- return baseA === baseB && baseA !== path19.basename(fileA) && baseA !== path19.basename(fileB);
32781
+ return baseA === baseB && baseA !== path20.basename(fileA) && baseA !== path20.basename(fileB);
32718
32782
  }
32719
32783
  function hasSharedPrefix(fileA, fileB) {
32720
- const dirA = path19.dirname(fileA);
32721
- const dirB = path19.dirname(fileB);
32784
+ const dirA = path20.dirname(fileA);
32785
+ const dirB = path20.dirname(fileB);
32722
32786
  if (dirA !== dirB) {
32723
32787
  return false;
32724
32788
  }
32725
- const baseA = path19.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
32726
- const baseB = path19.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
32789
+ const baseA = path20.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
32790
+ const baseB = path20.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
32727
32791
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
32728
32792
  return true;
32729
32793
  }
@@ -32777,8 +32841,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
32777
32841
  const entries = [];
32778
32842
  const now = new Date().toISOString();
32779
32843
  for (const pair of pairs.slice(0, 10)) {
32780
- const baseA = path19.basename(pair.fileA);
32781
- const baseB = path19.basename(pair.fileB);
32844
+ const baseA = path20.basename(pair.fileA);
32845
+ const baseB = path20.basename(pair.fileB);
32782
32846
  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.`;
32783
32847
  if (lesson.length > 280) {
32784
32848
  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.`;
@@ -32887,13 +32951,13 @@ __export(exports_config_doctor, {
32887
32951
  import * as crypto3 from "crypto";
32888
32952
  import * as fs13 from "fs";
32889
32953
  import * as os5 from "os";
32890
- import * as path22 from "path";
32954
+ import * as path23 from "path";
32891
32955
  function getUserConfigDir3() {
32892
- return process.env.XDG_CONFIG_HOME || path22.join(os5.homedir(), ".config");
32956
+ return process.env.XDG_CONFIG_HOME || path23.join(os5.homedir(), ".config");
32893
32957
  }
32894
32958
  function getConfigPaths(directory) {
32895
- const userConfigPath = path22.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
32896
- const projectConfigPath = path22.join(directory, ".opencode", "opencode-swarm.json");
32959
+ const userConfigPath = path23.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
32960
+ const projectConfigPath = path23.join(directory, ".opencode", "opencode-swarm.json");
32897
32961
  return { userConfigPath, projectConfigPath };
32898
32962
  }
32899
32963
  function computeHash(content) {
@@ -32918,9 +32982,9 @@ function isValidConfigPath(configPath, directory) {
32918
32982
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
32919
32983
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
32920
32984
  try {
32921
- const resolvedConfig = path22.resolve(configPath);
32922
- const resolvedUser = path22.resolve(normalizedUser);
32923
- const resolvedProject = path22.resolve(normalizedProject);
32985
+ const resolvedConfig = path23.resolve(configPath);
32986
+ const resolvedUser = path23.resolve(normalizedUser);
32987
+ const resolvedProject = path23.resolve(normalizedProject);
32924
32988
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
32925
32989
  } catch {
32926
32990
  return false;
@@ -32960,12 +33024,12 @@ function createConfigBackup(directory) {
32960
33024
  };
32961
33025
  }
32962
33026
  function writeBackupArtifact(directory, backup) {
32963
- const swarmDir = path22.join(directory, ".swarm");
33027
+ const swarmDir = path23.join(directory, ".swarm");
32964
33028
  if (!fs13.existsSync(swarmDir)) {
32965
33029
  fs13.mkdirSync(swarmDir, { recursive: true });
32966
33030
  }
32967
33031
  const backupFilename = `config-backup-${backup.createdAt}.json`;
32968
- const backupPath = path22.join(swarmDir, backupFilename);
33032
+ const backupPath = path23.join(swarmDir, backupFilename);
32969
33033
  const artifact = {
32970
33034
  createdAt: backup.createdAt,
32971
33035
  configPath: backup.configPath,
@@ -32995,7 +33059,7 @@ function restoreFromBackup(backupPath, directory) {
32995
33059
  return null;
32996
33060
  }
32997
33061
  const targetPath = artifact.configPath;
32998
- const targetDir = path22.dirname(targetPath);
33062
+ const targetDir = path23.dirname(targetPath);
32999
33063
  if (!fs13.existsSync(targetDir)) {
33000
33064
  fs13.mkdirSync(targetDir, { recursive: true });
33001
33065
  }
@@ -33026,9 +33090,9 @@ function readConfigFromFile(directory) {
33026
33090
  return null;
33027
33091
  }
33028
33092
  }
33029
- function validateConfigKey(path23, value, _config) {
33093
+ function validateConfigKey(path24, value, _config) {
33030
33094
  const findings = [];
33031
- switch (path23) {
33095
+ switch (path24) {
33032
33096
  case "agents": {
33033
33097
  if (value !== undefined) {
33034
33098
  findings.push({
@@ -33275,27 +33339,27 @@ function validateConfigKey(path23, value, _config) {
33275
33339
  }
33276
33340
  return findings;
33277
33341
  }
33278
- function walkConfigAndValidate(obj, path23, config3, findings) {
33342
+ function walkConfigAndValidate(obj, path24, config3, findings) {
33279
33343
  if (obj === null || obj === undefined) {
33280
33344
  return;
33281
33345
  }
33282
- if (path23 && typeof obj === "object" && !Array.isArray(obj)) {
33283
- const keyFindings = validateConfigKey(path23, obj, config3);
33346
+ if (path24 && typeof obj === "object" && !Array.isArray(obj)) {
33347
+ const keyFindings = validateConfigKey(path24, obj, config3);
33284
33348
  findings.push(...keyFindings);
33285
33349
  }
33286
33350
  if (typeof obj !== "object") {
33287
- const keyFindings = validateConfigKey(path23, obj, config3);
33351
+ const keyFindings = validateConfigKey(path24, obj, config3);
33288
33352
  findings.push(...keyFindings);
33289
33353
  return;
33290
33354
  }
33291
33355
  if (Array.isArray(obj)) {
33292
33356
  obj.forEach((item, index) => {
33293
- walkConfigAndValidate(item, `${path23}[${index}]`, config3, findings);
33357
+ walkConfigAndValidate(item, `${path24}[${index}]`, config3, findings);
33294
33358
  });
33295
33359
  return;
33296
33360
  }
33297
33361
  for (const [key, value] of Object.entries(obj)) {
33298
- const newPath = path23 ? `${path23}.${key}` : key;
33362
+ const newPath = path24 ? `${path24}.${key}` : key;
33299
33363
  walkConfigAndValidate(value, newPath, config3, findings);
33300
33364
  }
33301
33365
  }
@@ -33415,7 +33479,7 @@ function applySafeAutoFixes(directory, result) {
33415
33479
  }
33416
33480
  }
33417
33481
  if (appliedFixes.length > 0) {
33418
- const configDir = path22.dirname(configPath);
33482
+ const configDir = path23.dirname(configPath);
33419
33483
  if (!fs13.existsSync(configDir)) {
33420
33484
  fs13.mkdirSync(configDir, { recursive: true });
33421
33485
  }
@@ -33425,12 +33489,12 @@ function applySafeAutoFixes(directory, result) {
33425
33489
  return { appliedFixes, updatedConfigPath };
33426
33490
  }
33427
33491
  function writeDoctorArtifact(directory, result) {
33428
- const swarmDir = path22.join(directory, ".swarm");
33492
+ const swarmDir = path23.join(directory, ".swarm");
33429
33493
  if (!fs13.existsSync(swarmDir)) {
33430
33494
  fs13.mkdirSync(swarmDir, { recursive: true });
33431
33495
  }
33432
33496
  const artifactFilename = "config-doctor.json";
33433
- const artifactPath = path22.join(swarmDir, artifactFilename);
33497
+ const artifactPath = path23.join(swarmDir, artifactFilename);
33434
33498
  const guiOutput = {
33435
33499
  timestamp: result.timestamp,
33436
33500
  summary: result.summary,
@@ -34484,7 +34548,7 @@ var init_detector = __esm(() => {
34484
34548
 
34485
34549
  // src/build/discovery.ts
34486
34550
  import * as fs14 from "fs";
34487
- import * as path24 from "path";
34551
+ import * as path25 from "path";
34488
34552
  function isCommandAvailable(command) {
34489
34553
  if (toolchainCache.has(command)) {
34490
34554
  return toolchainCache.get(command);
@@ -34517,11 +34581,11 @@ function findBuildFiles(workingDir, patterns) {
34517
34581
  const regex = simpleGlobToRegex(pattern);
34518
34582
  const matches = files.filter((f) => regex.test(f));
34519
34583
  if (matches.length > 0) {
34520
- return path24.join(dir, matches[0]);
34584
+ return path25.join(dir, matches[0]);
34521
34585
  }
34522
34586
  } catch {}
34523
34587
  } else {
34524
- const filePath = path24.join(workingDir, pattern);
34588
+ const filePath = path25.join(workingDir, pattern);
34525
34589
  if (fs14.existsSync(filePath)) {
34526
34590
  return filePath;
34527
34591
  }
@@ -34530,7 +34594,7 @@ function findBuildFiles(workingDir, patterns) {
34530
34594
  return null;
34531
34595
  }
34532
34596
  function getRepoDefinedScripts(workingDir, scripts) {
34533
- const packageJsonPath = path24.join(workingDir, "package.json");
34597
+ const packageJsonPath = path25.join(workingDir, "package.json");
34534
34598
  if (!fs14.existsSync(packageJsonPath)) {
34535
34599
  return [];
34536
34600
  }
@@ -34571,7 +34635,7 @@ function findAllBuildFiles(workingDir) {
34571
34635
  const regex = simpleGlobToRegex(pattern);
34572
34636
  findFilesRecursive(workingDir, regex, allBuildFiles);
34573
34637
  } else {
34574
- const filePath = path24.join(workingDir, pattern);
34638
+ const filePath = path25.join(workingDir, pattern);
34575
34639
  if (fs14.existsSync(filePath)) {
34576
34640
  allBuildFiles.add(filePath);
34577
34641
  }
@@ -34584,7 +34648,7 @@ function findFilesRecursive(dir, regex, results) {
34584
34648
  try {
34585
34649
  const entries = fs14.readdirSync(dir, { withFileTypes: true });
34586
34650
  for (const entry of entries) {
34587
- const fullPath = path24.join(dir, entry.name);
34651
+ const fullPath = path25.join(dir, entry.name);
34588
34652
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
34589
34653
  findFilesRecursive(fullPath, regex, results);
34590
34654
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -34607,7 +34671,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
34607
34671
  let foundCommand = false;
34608
34672
  for (const cmd of sortedCommands) {
34609
34673
  if (cmd.detectFile) {
34610
- const detectFilePath = path24.join(workingDir, cmd.detectFile);
34674
+ const detectFilePath = path25.join(workingDir, cmd.detectFile);
34611
34675
  if (!fs14.existsSync(detectFilePath)) {
34612
34676
  continue;
34613
34677
  }
@@ -34864,7 +34928,7 @@ function validateDirectory(directory) {
34864
34928
 
34865
34929
  // src/tools/lint.ts
34866
34930
  import * as fs15 from "fs";
34867
- import * as path25 from "path";
34931
+ import * as path26 from "path";
34868
34932
  function validateArgs(args2) {
34869
34933
  if (typeof args2 !== "object" || args2 === null)
34870
34934
  return false;
@@ -34875,9 +34939,9 @@ function validateArgs(args2) {
34875
34939
  }
34876
34940
  function getLinterCommand(linter, mode, projectDir) {
34877
34941
  const isWindows = process.platform === "win32";
34878
- const binDir = path25.join(projectDir, "node_modules", ".bin");
34879
- const biomeBin = isWindows ? path25.join(binDir, "biome.EXE") : path25.join(binDir, "biome");
34880
- const eslintBin = isWindows ? path25.join(binDir, "eslint.cmd") : path25.join(binDir, "eslint");
34942
+ const binDir = path26.join(projectDir, "node_modules", ".bin");
34943
+ const biomeBin = isWindows ? path26.join(binDir, "biome.EXE") : path26.join(binDir, "biome");
34944
+ const eslintBin = isWindows ? path26.join(binDir, "eslint.cmd") : path26.join(binDir, "eslint");
34881
34945
  switch (linter) {
34882
34946
  case "biome":
34883
34947
  if (mode === "fix") {
@@ -34893,7 +34957,7 @@ function getLinterCommand(linter, mode, projectDir) {
34893
34957
  }
34894
34958
  function getAdditionalLinterCommand(linter, mode, cwd) {
34895
34959
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
34896
- const gradlew = fs15.existsSync(path25.join(cwd, gradlewName)) ? path25.join(cwd, gradlewName) : null;
34960
+ const gradlew = fs15.existsSync(path26.join(cwd, gradlewName)) ? path26.join(cwd, gradlewName) : null;
34897
34961
  switch (linter) {
34898
34962
  case "ruff":
34899
34963
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -34927,10 +34991,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
34927
34991
  }
34928
34992
  }
34929
34993
  function detectRuff(cwd) {
34930
- if (fs15.existsSync(path25.join(cwd, "ruff.toml")))
34994
+ if (fs15.existsSync(path26.join(cwd, "ruff.toml")))
34931
34995
  return isCommandAvailable("ruff");
34932
34996
  try {
34933
- const pyproject = path25.join(cwd, "pyproject.toml");
34997
+ const pyproject = path26.join(cwd, "pyproject.toml");
34934
34998
  if (fs15.existsSync(pyproject)) {
34935
34999
  const content = fs15.readFileSync(pyproject, "utf-8");
34936
35000
  if (content.includes("[tool.ruff]"))
@@ -34940,19 +35004,19 @@ function detectRuff(cwd) {
34940
35004
  return false;
34941
35005
  }
34942
35006
  function detectClippy(cwd) {
34943
- return fs15.existsSync(path25.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
35007
+ return fs15.existsSync(path26.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
34944
35008
  }
34945
35009
  function detectGolangciLint(cwd) {
34946
- return fs15.existsSync(path25.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
35010
+ return fs15.existsSync(path26.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
34947
35011
  }
34948
35012
  function detectCheckstyle(cwd) {
34949
- const hasMaven = fs15.existsSync(path25.join(cwd, "pom.xml"));
34950
- const hasGradle = fs15.existsSync(path25.join(cwd, "build.gradle")) || fs15.existsSync(path25.join(cwd, "build.gradle.kts"));
34951
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(path25.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
35013
+ const hasMaven = fs15.existsSync(path26.join(cwd, "pom.xml"));
35014
+ const hasGradle = fs15.existsSync(path26.join(cwd, "build.gradle")) || fs15.existsSync(path26.join(cwd, "build.gradle.kts"));
35015
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(path26.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
34952
35016
  return (hasMaven || hasGradle) && hasBinary;
34953
35017
  }
34954
35018
  function detectKtlint(cwd) {
34955
- const hasKotlin = fs15.existsSync(path25.join(cwd, "build.gradle.kts")) || fs15.existsSync(path25.join(cwd, "build.gradle")) || (() => {
35019
+ const hasKotlin = fs15.existsSync(path26.join(cwd, "build.gradle.kts")) || fs15.existsSync(path26.join(cwd, "build.gradle")) || (() => {
34956
35020
  try {
34957
35021
  return fs15.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
34958
35022
  } catch {
@@ -34971,11 +35035,11 @@ function detectDotnetFormat(cwd) {
34971
35035
  }
34972
35036
  }
34973
35037
  function detectCppcheck(cwd) {
34974
- if (fs15.existsSync(path25.join(cwd, "CMakeLists.txt"))) {
35038
+ if (fs15.existsSync(path26.join(cwd, "CMakeLists.txt"))) {
34975
35039
  return isCommandAvailable("cppcheck");
34976
35040
  }
34977
35041
  try {
34978
- const dirsToCheck = [cwd, path25.join(cwd, "src")];
35042
+ const dirsToCheck = [cwd, path26.join(cwd, "src")];
34979
35043
  const hasCpp = dirsToCheck.some((dir) => {
34980
35044
  try {
34981
35045
  return fs15.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -34989,13 +35053,13 @@ function detectCppcheck(cwd) {
34989
35053
  }
34990
35054
  }
34991
35055
  function detectSwiftlint(cwd) {
34992
- return fs15.existsSync(path25.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
35056
+ return fs15.existsSync(path26.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
34993
35057
  }
34994
35058
  function detectDartAnalyze(cwd) {
34995
- return fs15.existsSync(path25.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
35059
+ return fs15.existsSync(path26.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
34996
35060
  }
34997
35061
  function detectRubocop(cwd) {
34998
- return (fs15.existsSync(path25.join(cwd, "Gemfile")) || fs15.existsSync(path25.join(cwd, "gems.rb")) || fs15.existsSync(path25.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
35062
+ return (fs15.existsSync(path26.join(cwd, "Gemfile")) || fs15.existsSync(path26.join(cwd, "gems.rb")) || fs15.existsSync(path26.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
34999
35063
  }
35000
35064
  function detectAdditionalLinter(cwd) {
35001
35065
  if (detectRuff(cwd))
@@ -35023,10 +35087,10 @@ function detectAdditionalLinter(cwd) {
35023
35087
  function resolveLinterBinPath(linter, projectDir) {
35024
35088
  const isWindows = process.platform === "win32";
35025
35089
  const binName = linter === "biome" ? isWindows ? "biome.EXE" : "biome" : isWindows ? "eslint.cmd" : "eslint";
35026
- const localBin = path25.join(projectDir, "node_modules", ".bin", binName);
35090
+ const localBin = path26.join(projectDir, "node_modules", ".bin", binName);
35027
35091
  if (fs15.existsSync(localBin))
35028
35092
  return localBin;
35029
- const ancestor = findBinInAncestors(path25.dirname(projectDir), binName);
35093
+ const ancestor = findBinInAncestors(path26.dirname(projectDir), binName);
35030
35094
  if (ancestor)
35031
35095
  return ancestor;
35032
35096
  const fromPath = findBinInEnvPath(binName);
@@ -35037,10 +35101,10 @@ function resolveLinterBinPath(linter, projectDir) {
35037
35101
  function findBinInAncestors(startDir, binName) {
35038
35102
  let dir = startDir;
35039
35103
  while (true) {
35040
- const candidate = path25.join(dir, "node_modules", ".bin", binName);
35104
+ const candidate = path26.join(dir, "node_modules", ".bin", binName);
35041
35105
  if (fs15.existsSync(candidate))
35042
35106
  return candidate;
35043
- const parent = path25.dirname(dir);
35107
+ const parent = path26.dirname(dir);
35044
35108
  if (parent === dir)
35045
35109
  break;
35046
35110
  dir = parent;
@@ -35049,10 +35113,10 @@ function findBinInAncestors(startDir, binName) {
35049
35113
  }
35050
35114
  function findBinInEnvPath(binName) {
35051
35115
  const searchPath = process.env.PATH ?? "";
35052
- for (const dir of searchPath.split(path25.delimiter)) {
35116
+ for (const dir of searchPath.split(path26.delimiter)) {
35053
35117
  if (!dir)
35054
35118
  continue;
35055
- const candidate = path25.join(dir, binName);
35119
+ const candidate = path26.join(dir, binName);
35056
35120
  if (fs15.existsSync(candidate))
35057
35121
  return candidate;
35058
35122
  }
@@ -35065,13 +35129,13 @@ async function detectAvailableLinter(directory) {
35065
35129
  return null;
35066
35130
  const projectDir = directory;
35067
35131
  const isWindows = process.platform === "win32";
35068
- const biomeBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "biome.EXE") : path25.join(projectDir, "node_modules", ".bin", "biome");
35069
- const eslintBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path25.join(projectDir, "node_modules", ".bin", "eslint");
35132
+ const biomeBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "biome.EXE") : path26.join(projectDir, "node_modules", ".bin", "biome");
35133
+ const eslintBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path26.join(projectDir, "node_modules", ".bin", "eslint");
35070
35134
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
35071
35135
  if (localResult)
35072
35136
  return localResult;
35073
- const biomeAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
35074
- const eslintAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
35137
+ const biomeAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
35138
+ const eslintAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
35075
35139
  if (biomeAncestor || eslintAncestor) {
35076
35140
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
35077
35141
  }
@@ -35286,7 +35350,7 @@ For Rust: rustup component add clippy`
35286
35350
 
35287
35351
  // src/tools/secretscan.ts
35288
35352
  import * as fs16 from "fs";
35289
- import * as path26 from "path";
35353
+ import * as path27 from "path";
35290
35354
  function calculateShannonEntropy(str) {
35291
35355
  if (str.length === 0)
35292
35356
  return 0;
@@ -35334,7 +35398,7 @@ function isGlobOrPathPattern(pattern) {
35334
35398
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
35335
35399
  }
35336
35400
  function loadSecretScanIgnore(scanDir) {
35337
- const ignorePath = path26.join(scanDir, ".secretscanignore");
35401
+ const ignorePath = path27.join(scanDir, ".secretscanignore");
35338
35402
  try {
35339
35403
  if (!fs16.existsSync(ignorePath))
35340
35404
  return [];
@@ -35357,7 +35421,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
35357
35421
  if (exactNames.has(entry))
35358
35422
  return true;
35359
35423
  for (const pattern of globPatterns) {
35360
- if (path26.matchesGlob(relPath, pattern))
35424
+ if (path27.matchesGlob(relPath, pattern))
35361
35425
  return true;
35362
35426
  }
35363
35427
  return false;
@@ -35378,7 +35442,7 @@ function validateDirectoryInput(dir) {
35378
35442
  return null;
35379
35443
  }
35380
35444
  function isBinaryFile(filePath, buffer) {
35381
- const ext = path26.extname(filePath).toLowerCase();
35445
+ const ext = path27.extname(filePath).toLowerCase();
35382
35446
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
35383
35447
  return true;
35384
35448
  }
@@ -35514,9 +35578,9 @@ function isSymlinkLoop(realPath, visited) {
35514
35578
  return false;
35515
35579
  }
35516
35580
  function isPathWithinScope(realPath, scanDir) {
35517
- const resolvedScanDir = path26.resolve(scanDir);
35518
- const resolvedRealPath = path26.resolve(realPath);
35519
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path26.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
35581
+ const resolvedScanDir = path27.resolve(scanDir);
35582
+ const resolvedRealPath = path27.resolve(realPath);
35583
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path27.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
35520
35584
  }
35521
35585
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
35522
35586
  skippedDirs: 0,
@@ -35542,8 +35606,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
35542
35606
  return a.localeCompare(b);
35543
35607
  });
35544
35608
  for (const entry of entries) {
35545
- const fullPath = path26.join(dir, entry);
35546
- const relPath = path26.relative(scanDir, fullPath).replace(/\\/g, "/");
35609
+ const fullPath = path27.join(dir, entry);
35610
+ const relPath = path27.relative(scanDir, fullPath).replace(/\\/g, "/");
35547
35611
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
35548
35612
  stats.skippedDirs++;
35549
35613
  continue;
@@ -35578,7 +35642,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
35578
35642
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
35579
35643
  files.push(...subFiles);
35580
35644
  } else if (lstat.isFile()) {
35581
- const ext = path26.extname(fullPath).toLowerCase();
35645
+ const ext = path27.extname(fullPath).toLowerCase();
35582
35646
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
35583
35647
  files.push(fullPath);
35584
35648
  } else {
@@ -35836,7 +35900,7 @@ var init_secretscan = __esm(() => {
35836
35900
  }
35837
35901
  }
35838
35902
  try {
35839
- const _scanDirRaw = path26.resolve(directory);
35903
+ const _scanDirRaw = path27.resolve(directory);
35840
35904
  const scanDir = (() => {
35841
35905
  try {
35842
35906
  return fs16.realpathSync(_scanDirRaw);
@@ -35979,7 +36043,7 @@ var init_secretscan = __esm(() => {
35979
36043
 
35980
36044
  // src/tools/resolve-working-directory.ts
35981
36045
  import * as fs17 from "fs";
35982
- import * as path27 from "path";
36046
+ import * as path28 from "path";
35983
36047
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
35984
36048
  if (workingDirectory == null || workingDirectory === "") {
35985
36049
  return { success: true, directory: fallbackDirectory };
@@ -35999,15 +36063,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
35999
36063
  };
36000
36064
  }
36001
36065
  }
36002
- const normalizedDir = path27.normalize(workingDirectory);
36003
- const pathParts = normalizedDir.split(path27.sep);
36066
+ const normalizedDir = path28.normalize(workingDirectory);
36067
+ const pathParts = normalizedDir.split(path28.sep);
36004
36068
  if (pathParts.includes("..")) {
36005
36069
  return {
36006
36070
  success: false,
36007
36071
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
36008
36072
  };
36009
36073
  }
36010
- const resolvedDir = path27.resolve(normalizedDir);
36074
+ const resolvedDir = path28.resolve(normalizedDir);
36011
36075
  try {
36012
36076
  const realPath = fs17.realpathSync(resolvedDir);
36013
36077
  return { success: true, directory: realPath };
@@ -36022,7 +36086,7 @@ var init_resolve_working_directory = () => {};
36022
36086
 
36023
36087
  // src/tools/test-runner.ts
36024
36088
  import * as fs18 from "fs";
36025
- import * as path28 from "path";
36089
+ import * as path29 from "path";
36026
36090
  function isAbsolutePath(str) {
36027
36091
  if (str.startsWith("/"))
36028
36092
  return true;
@@ -36087,14 +36151,14 @@ function hasDevDependency(devDeps, ...patterns) {
36087
36151
  return hasPackageJsonDependency(devDeps, ...patterns);
36088
36152
  }
36089
36153
  function detectGoTest(cwd) {
36090
- return fs18.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("go");
36154
+ return fs18.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("go");
36091
36155
  }
36092
36156
  function detectJavaMaven(cwd) {
36093
- return fs18.existsSync(path28.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
36157
+ return fs18.existsSync(path29.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
36094
36158
  }
36095
36159
  function detectGradle(cwd) {
36096
- const hasBuildFile = fs18.existsSync(path28.join(cwd, "build.gradle")) || fs18.existsSync(path28.join(cwd, "build.gradle.kts"));
36097
- const hasGradlew = fs18.existsSync(path28.join(cwd, "gradlew")) || fs18.existsSync(path28.join(cwd, "gradlew.bat"));
36160
+ const hasBuildFile = fs18.existsSync(path29.join(cwd, "build.gradle")) || fs18.existsSync(path29.join(cwd, "build.gradle.kts"));
36161
+ const hasGradlew = fs18.existsSync(path29.join(cwd, "gradlew")) || fs18.existsSync(path29.join(cwd, "gradlew.bat"));
36098
36162
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
36099
36163
  }
36100
36164
  function detectDotnetTest(cwd) {
@@ -36107,30 +36171,30 @@ function detectDotnetTest(cwd) {
36107
36171
  }
36108
36172
  }
36109
36173
  function detectCTest(cwd) {
36110
- const hasSource = fs18.existsSync(path28.join(cwd, "CMakeLists.txt"));
36111
- const hasBuildCache = fs18.existsSync(path28.join(cwd, "CMakeCache.txt")) || fs18.existsSync(path28.join(cwd, "build", "CMakeCache.txt"));
36174
+ const hasSource = fs18.existsSync(path29.join(cwd, "CMakeLists.txt"));
36175
+ const hasBuildCache = fs18.existsSync(path29.join(cwd, "CMakeCache.txt")) || fs18.existsSync(path29.join(cwd, "build", "CMakeCache.txt"));
36112
36176
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
36113
36177
  }
36114
36178
  function detectSwiftTest(cwd) {
36115
- return fs18.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swift");
36179
+ return fs18.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swift");
36116
36180
  }
36117
36181
  function detectDartTest(cwd) {
36118
- return fs18.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
36182
+ return fs18.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
36119
36183
  }
36120
36184
  function detectRSpec(cwd) {
36121
- const hasRSpecFile = fs18.existsSync(path28.join(cwd, ".rspec"));
36122
- const hasGemfile = fs18.existsSync(path28.join(cwd, "Gemfile"));
36123
- const hasSpecDir = fs18.existsSync(path28.join(cwd, "spec"));
36185
+ const hasRSpecFile = fs18.existsSync(path29.join(cwd, ".rspec"));
36186
+ const hasGemfile = fs18.existsSync(path29.join(cwd, "Gemfile"));
36187
+ const hasSpecDir = fs18.existsSync(path29.join(cwd, "spec"));
36124
36188
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
36125
36189
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
36126
36190
  }
36127
36191
  function detectMinitest(cwd) {
36128
- return fs18.existsSync(path28.join(cwd, "test")) && (fs18.existsSync(path28.join(cwd, "Gemfile")) || fs18.existsSync(path28.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
36192
+ return fs18.existsSync(path29.join(cwd, "test")) && (fs18.existsSync(path29.join(cwd, "Gemfile")) || fs18.existsSync(path29.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
36129
36193
  }
36130
36194
  async function detectTestFramework(cwd) {
36131
36195
  const baseDir = cwd;
36132
36196
  try {
36133
- const packageJsonPath = path28.join(baseDir, "package.json");
36197
+ const packageJsonPath = path29.join(baseDir, "package.json");
36134
36198
  if (fs18.existsSync(packageJsonPath)) {
36135
36199
  const content = fs18.readFileSync(packageJsonPath, "utf-8");
36136
36200
  const pkg = JSON.parse(content);
@@ -36151,16 +36215,16 @@ async function detectTestFramework(cwd) {
36151
36215
  return "jest";
36152
36216
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
36153
36217
  return "mocha";
36154
- if (fs18.existsSync(path28.join(baseDir, "bun.lockb")) || fs18.existsSync(path28.join(baseDir, "bun.lock"))) {
36218
+ if (fs18.existsSync(path29.join(baseDir, "bun.lockb")) || fs18.existsSync(path29.join(baseDir, "bun.lock"))) {
36155
36219
  if (scripts.test?.includes("bun"))
36156
36220
  return "bun";
36157
36221
  }
36158
36222
  }
36159
36223
  } catch {}
36160
36224
  try {
36161
- const pyprojectTomlPath = path28.join(baseDir, "pyproject.toml");
36162
- const setupCfgPath = path28.join(baseDir, "setup.cfg");
36163
- const requirementsTxtPath = path28.join(baseDir, "requirements.txt");
36225
+ const pyprojectTomlPath = path29.join(baseDir, "pyproject.toml");
36226
+ const setupCfgPath = path29.join(baseDir, "setup.cfg");
36227
+ const requirementsTxtPath = path29.join(baseDir, "requirements.txt");
36164
36228
  if (fs18.existsSync(pyprojectTomlPath)) {
36165
36229
  const content = fs18.readFileSync(pyprojectTomlPath, "utf-8");
36166
36230
  if (content.includes("[tool.pytest"))
@@ -36180,7 +36244,7 @@ async function detectTestFramework(cwd) {
36180
36244
  }
36181
36245
  } catch {}
36182
36246
  try {
36183
- const cargoTomlPath = path28.join(baseDir, "Cargo.toml");
36247
+ const cargoTomlPath = path29.join(baseDir, "Cargo.toml");
36184
36248
  if (fs18.existsSync(cargoTomlPath)) {
36185
36249
  const content = fs18.readFileSync(cargoTomlPath, "utf-8");
36186
36250
  if (content.includes("[dev-dependencies]")) {
@@ -36191,9 +36255,9 @@ async function detectTestFramework(cwd) {
36191
36255
  }
36192
36256
  } catch {}
36193
36257
  try {
36194
- const pesterConfigPath = path28.join(baseDir, "pester.config.ps1");
36195
- const pesterConfigJsonPath = path28.join(baseDir, "pester.config.ps1.json");
36196
- const pesterPs1Path = path28.join(baseDir, "tests.ps1");
36258
+ const pesterConfigPath = path29.join(baseDir, "pester.config.ps1");
36259
+ const pesterConfigJsonPath = path29.join(baseDir, "pester.config.ps1.json");
36260
+ const pesterPs1Path = path29.join(baseDir, "tests.ps1");
36197
36261
  if (fs18.existsSync(pesterConfigPath) || fs18.existsSync(pesterConfigJsonPath) || fs18.existsSync(pesterPs1Path)) {
36198
36262
  return "pester";
36199
36263
  }
@@ -36226,8 +36290,8 @@ function getTestFilesFromConvention(sourceFiles) {
36226
36290
  const testFiles = [];
36227
36291
  for (const file3 of sourceFiles) {
36228
36292
  const normalizedPath = file3.replace(/\\/g, "/");
36229
- const basename5 = path28.basename(file3);
36230
- const dirname12 = path28.dirname(file3);
36293
+ const basename5 = path29.basename(file3);
36294
+ const dirname12 = path29.dirname(file3);
36231
36295
  if (hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
36232
36296
  if (!testFiles.includes(file3)) {
36233
36297
  testFiles.push(file3);
@@ -36236,13 +36300,13 @@ function getTestFilesFromConvention(sourceFiles) {
36236
36300
  }
36237
36301
  for (const _pattern of TEST_PATTERNS) {
36238
36302
  const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
36239
- const ext = path28.extname(basename5);
36303
+ const ext = path29.extname(basename5);
36240
36304
  const possibleTestFiles = [
36241
- path28.join(dirname12, `${nameWithoutExt}.spec${ext}`),
36242
- path28.join(dirname12, `${nameWithoutExt}.test${ext}`),
36243
- path28.join(dirname12, "__tests__", `${nameWithoutExt}${ext}`),
36244
- path28.join(dirname12, "tests", `${nameWithoutExt}${ext}`),
36245
- path28.join(dirname12, "test", `${nameWithoutExt}${ext}`)
36305
+ path29.join(dirname12, `${nameWithoutExt}.spec${ext}`),
36306
+ path29.join(dirname12, `${nameWithoutExt}.test${ext}`),
36307
+ path29.join(dirname12, "__tests__", `${nameWithoutExt}${ext}`),
36308
+ path29.join(dirname12, "tests", `${nameWithoutExt}${ext}`),
36309
+ path29.join(dirname12, "test", `${nameWithoutExt}${ext}`)
36246
36310
  ];
36247
36311
  for (const testFile of possibleTestFiles) {
36248
36312
  if (fs18.existsSync(testFile) && !testFiles.includes(testFile)) {
@@ -36262,7 +36326,7 @@ async function getTestFilesFromGraph(sourceFiles) {
36262
36326
  for (const testFile of candidateTestFiles) {
36263
36327
  try {
36264
36328
  const content = fs18.readFileSync(testFile, "utf-8");
36265
- const testDir = path28.dirname(testFile);
36329
+ const testDir = path29.dirname(testFile);
36266
36330
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
36267
36331
  let match;
36268
36332
  match = importRegex.exec(content);
@@ -36270,8 +36334,8 @@ async function getTestFilesFromGraph(sourceFiles) {
36270
36334
  const importPath = match[1];
36271
36335
  let resolvedImport;
36272
36336
  if (importPath.startsWith(".")) {
36273
- resolvedImport = path28.resolve(testDir, importPath);
36274
- const existingExt = path28.extname(resolvedImport);
36337
+ resolvedImport = path29.resolve(testDir, importPath);
36338
+ const existingExt = path29.extname(resolvedImport);
36275
36339
  if (!existingExt) {
36276
36340
  for (const extToTry of [
36277
36341
  ".ts",
@@ -36291,12 +36355,12 @@ async function getTestFilesFromGraph(sourceFiles) {
36291
36355
  } else {
36292
36356
  continue;
36293
36357
  }
36294
- const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
36295
- const importDir = path28.dirname(resolvedImport);
36358
+ const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
36359
+ const importDir = path29.dirname(resolvedImport);
36296
36360
  for (const sourceFile of sourceFiles) {
36297
- const sourceDir = path28.dirname(sourceFile);
36298
- const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
36299
- const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test");
36361
+ const sourceDir = path29.dirname(sourceFile);
36362
+ const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
36363
+ const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
36300
36364
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
36301
36365
  if (!testFiles.includes(testFile)) {
36302
36366
  testFiles.push(testFile);
@@ -36311,8 +36375,8 @@ async function getTestFilesFromGraph(sourceFiles) {
36311
36375
  while (match !== null) {
36312
36376
  const importPath = match[1];
36313
36377
  if (importPath.startsWith(".")) {
36314
- let resolvedImport = path28.resolve(testDir, importPath);
36315
- const existingExt = path28.extname(resolvedImport);
36378
+ let resolvedImport = path29.resolve(testDir, importPath);
36379
+ const existingExt = path29.extname(resolvedImport);
36316
36380
  if (!existingExt) {
36317
36381
  for (const extToTry of [
36318
36382
  ".ts",
@@ -36329,12 +36393,12 @@ async function getTestFilesFromGraph(sourceFiles) {
36329
36393
  }
36330
36394
  }
36331
36395
  }
36332
- const importDir = path28.dirname(resolvedImport);
36333
- const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
36396
+ const importDir = path29.dirname(resolvedImport);
36397
+ const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
36334
36398
  for (const sourceFile of sourceFiles) {
36335
- const sourceDir = path28.dirname(sourceFile);
36336
- const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
36337
- const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test");
36399
+ const sourceDir = path29.dirname(sourceFile);
36400
+ const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
36401
+ const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
36338
36402
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
36339
36403
  if (!testFiles.includes(testFile)) {
36340
36404
  testFiles.push(testFile);
@@ -36419,8 +36483,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
36419
36483
  return ["mvn", "test"];
36420
36484
  case "gradle": {
36421
36485
  const isWindows = process.platform === "win32";
36422
- const hasGradlewBat = fs18.existsSync(path28.join(baseDir, "gradlew.bat"));
36423
- const hasGradlew = fs18.existsSync(path28.join(baseDir, "gradlew"));
36486
+ const hasGradlewBat = fs18.existsSync(path29.join(baseDir, "gradlew.bat"));
36487
+ const hasGradlew = fs18.existsSync(path29.join(baseDir, "gradlew"));
36424
36488
  if (hasGradlewBat && isWindows)
36425
36489
  return ["gradlew.bat", "test"];
36426
36490
  if (hasGradlew)
@@ -36437,7 +36501,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
36437
36501
  "cmake-build-release",
36438
36502
  "out"
36439
36503
  ];
36440
- const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(path28.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
36504
+ const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(path29.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
36441
36505
  return ["ctest", "--test-dir", actualBuildDir];
36442
36506
  }
36443
36507
  case "swift-test":
@@ -37005,7 +37069,7 @@ var init_test_runner = __esm(() => {
37005
37069
  let effectiveScope = scope;
37006
37070
  if (scope === "all") {} else if (scope === "convention") {
37007
37071
  const sourceFiles = args2.files.filter((f) => {
37008
- const ext = path28.extname(f).toLowerCase();
37072
+ const ext = path29.extname(f).toLowerCase();
37009
37073
  return SOURCE_EXTENSIONS.has(ext);
37010
37074
  });
37011
37075
  if (sourceFiles.length === 0) {
@@ -37021,7 +37085,7 @@ var init_test_runner = __esm(() => {
37021
37085
  testFiles = getTestFilesFromConvention(sourceFiles);
37022
37086
  } else if (scope === "graph") {
37023
37087
  const sourceFiles = args2.files.filter((f) => {
37024
- const ext = path28.extname(f).toLowerCase();
37088
+ const ext = path29.extname(f).toLowerCase();
37025
37089
  return SOURCE_EXTENSIONS.has(ext);
37026
37090
  });
37027
37091
  if (sourceFiles.length === 0) {
@@ -37075,7 +37139,7 @@ var init_test_runner = __esm(() => {
37075
37139
 
37076
37140
  // src/services/preflight-service.ts
37077
37141
  import * as fs19 from "fs";
37078
- import * as path29 from "path";
37142
+ import * as path30 from "path";
37079
37143
  function validateDirectoryPath(dir) {
37080
37144
  if (!dir || typeof dir !== "string") {
37081
37145
  throw new Error("Directory path is required");
@@ -37083,8 +37147,8 @@ function validateDirectoryPath(dir) {
37083
37147
  if (dir.includes("..")) {
37084
37148
  throw new Error("Directory path must not contain path traversal sequences");
37085
37149
  }
37086
- const normalized = path29.normalize(dir);
37087
- const absolutePath = path29.isAbsolute(normalized) ? normalized : path29.resolve(normalized);
37150
+ const normalized = path30.normalize(dir);
37151
+ const absolutePath = path30.isAbsolute(normalized) ? normalized : path30.resolve(normalized);
37088
37152
  return absolutePath;
37089
37153
  }
37090
37154
  function validateTimeout(timeoutMs, defaultValue) {
@@ -37107,7 +37171,7 @@ function validateTimeout(timeoutMs, defaultValue) {
37107
37171
  }
37108
37172
  function getPackageVersion(dir) {
37109
37173
  try {
37110
- const packagePath = path29.join(dir, "package.json");
37174
+ const packagePath = path30.join(dir, "package.json");
37111
37175
  if (fs19.existsSync(packagePath)) {
37112
37176
  const content = fs19.readFileSync(packagePath, "utf-8");
37113
37177
  const pkg = JSON.parse(content);
@@ -37118,7 +37182,7 @@ function getPackageVersion(dir) {
37118
37182
  }
37119
37183
  function getChangelogVersion(dir) {
37120
37184
  try {
37121
- const changelogPath = path29.join(dir, "CHANGELOG.md");
37185
+ const changelogPath = path30.join(dir, "CHANGELOG.md");
37122
37186
  if (fs19.existsSync(changelogPath)) {
37123
37187
  const content = fs19.readFileSync(changelogPath, "utf-8");
37124
37188
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -37132,7 +37196,7 @@ function getChangelogVersion(dir) {
37132
37196
  function getVersionFileVersion(dir) {
37133
37197
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
37134
37198
  for (const file3 of possibleFiles) {
37135
- const filePath = path29.join(dir, file3);
37199
+ const filePath = path30.join(dir, file3);
37136
37200
  if (fs19.existsSync(filePath)) {
37137
37201
  try {
37138
37202
  const content = fs19.readFileSync(filePath, "utf-8").trim();
@@ -37660,7 +37724,7 @@ __export(exports_gate_evidence, {
37660
37724
  DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
37661
37725
  });
37662
37726
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync17, renameSync as renameSync10, unlinkSync as unlinkSync5 } from "fs";
37663
- import * as path36 from "path";
37727
+ import * as path37 from "path";
37664
37728
  function isValidTaskId2(taskId) {
37665
37729
  if (!taskId)
37666
37730
  return false;
@@ -37707,10 +37771,10 @@ function expandRequiredGates(existingGates, newAgentType) {
37707
37771
  return combined.sort();
37708
37772
  }
37709
37773
  function getEvidenceDir(directory) {
37710
- return path36.join(directory, ".swarm", "evidence");
37774
+ return path37.join(directory, ".swarm", "evidence");
37711
37775
  }
37712
37776
  function getEvidencePath(directory, taskId) {
37713
- return path36.join(getEvidenceDir(directory), `${taskId}.json`);
37777
+ return path37.join(getEvidenceDir(directory), `${taskId}.json`);
37714
37778
  }
37715
37779
  function readExisting(evidencePath) {
37716
37780
  try {
@@ -37821,12 +37885,12 @@ __export(exports_review_receipt, {
37821
37885
  });
37822
37886
  import * as crypto5 from "crypto";
37823
37887
  import * as fs28 from "fs";
37824
- import * as path38 from "path";
37888
+ import * as path39 from "path";
37825
37889
  function resolveReceiptsDir(directory) {
37826
- return path38.join(directory, ".swarm", "review-receipts");
37890
+ return path39.join(directory, ".swarm", "review-receipts");
37827
37891
  }
37828
37892
  function resolveReceiptIndexPath(directory) {
37829
- return path38.join(resolveReceiptsDir(directory), "index.json");
37893
+ return path39.join(resolveReceiptsDir(directory), "index.json");
37830
37894
  }
37831
37895
  function buildReceiptFilename(id, date9) {
37832
37896
  const dateStr = date9.toISOString().slice(0, 10);
@@ -37865,7 +37929,7 @@ async function readReceiptIndex(directory) {
37865
37929
  }
37866
37930
  async function writeReceiptIndex(directory, index) {
37867
37931
  const indexPath = resolveReceiptIndexPath(directory);
37868
- const dir = path38.dirname(indexPath);
37932
+ const dir = path39.dirname(indexPath);
37869
37933
  await fs28.promises.mkdir(dir, { recursive: true });
37870
37934
  const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
37871
37935
  await fs28.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
@@ -37876,7 +37940,7 @@ async function persistReviewReceipt(directory, receipt) {
37876
37940
  await fs28.promises.mkdir(receiptsDir, { recursive: true });
37877
37941
  const now = new Date(receipt.reviewed_at);
37878
37942
  const filename = buildReceiptFilename(receipt.id, now);
37879
- const receiptPath = path38.join(receiptsDir, filename);
37943
+ const receiptPath = path39.join(receiptsDir, filename);
37880
37944
  const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
37881
37945
  await fs28.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
37882
37946
  fs28.renameSync(tmpPath, receiptPath);
@@ -37898,7 +37962,7 @@ async function readReceiptById(directory, receiptId) {
37898
37962
  const entry = index.entries.find((e) => e.id === receiptId);
37899
37963
  if (!entry)
37900
37964
  return null;
37901
- const receiptPath = path38.join(resolveReceiptsDir(directory), entry.filename);
37965
+ const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
37902
37966
  try {
37903
37967
  const content = await fs28.promises.readFile(receiptPath, "utf-8");
37904
37968
  return JSON.parse(content);
@@ -37911,7 +37975,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
37911
37975
  const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
37912
37976
  const receipts = [];
37913
37977
  for (const entry of matching) {
37914
- const receiptPath = path38.join(resolveReceiptsDir(directory), entry.filename);
37978
+ const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
37915
37979
  try {
37916
37980
  const content = await fs28.promises.readFile(receiptPath, "utf-8");
37917
37981
  receipts.push(JSON.parse(content));
@@ -37924,7 +37988,7 @@ async function readAllReceipts(directory) {
37924
37988
  const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
37925
37989
  const receipts = [];
37926
37990
  for (const entry of sorted) {
37927
- const receiptPath = path38.join(resolveReceiptsDir(directory), entry.filename);
37991
+ const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
37928
37992
  try {
37929
37993
  const content = await fs28.promises.readFile(receiptPath, "utf-8");
37930
37994
  receipts.push(JSON.parse(content));
@@ -38060,13 +38124,13 @@ __export(exports_doc_scan, {
38060
38124
  import * as crypto6 from "crypto";
38061
38125
  import * as fs31 from "fs";
38062
38126
  import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
38063
- import * as path42 from "path";
38127
+ import * as path43 from "path";
38064
38128
  function normalizeSeparators(filePath) {
38065
38129
  return filePath.replace(/\\/g, "/");
38066
38130
  }
38067
38131
  function matchesDocPattern(filePath, patterns) {
38068
38132
  const normalizedPath = normalizeSeparators(filePath);
38069
- const basename6 = path42.basename(filePath);
38133
+ const basename6 = path43.basename(filePath);
38070
38134
  for (const pattern of patterns) {
38071
38135
  if (!pattern.includes("/") && !pattern.includes("\\")) {
38072
38136
  if (basename6 === pattern) {
@@ -38122,7 +38186,7 @@ function stripMarkdown(text) {
38122
38186
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
38123
38187
  }
38124
38188
  async function scanDocIndex(directory) {
38125
- const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
38189
+ const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
38126
38190
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
38127
38191
  const extraPatterns = [
38128
38192
  "ARCHITECTURE.md",
@@ -38139,7 +38203,7 @@ async function scanDocIndex(directory) {
38139
38203
  let cacheValid = true;
38140
38204
  for (const file3 of existingManifest.files) {
38141
38205
  try {
38142
- const fullPath = path42.join(directory, file3.path);
38206
+ const fullPath = path43.join(directory, file3.path);
38143
38207
  const stat2 = fs31.statSync(fullPath);
38144
38208
  if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
38145
38209
  cacheValid = false;
@@ -38169,7 +38233,7 @@ async function scanDocIndex(directory) {
38169
38233
  }
38170
38234
  const entries = rawEntries.filter((e) => typeof e === "string");
38171
38235
  for (const entry of entries) {
38172
- const fullPath = path42.join(directory, entry);
38236
+ const fullPath = path43.join(directory, entry);
38173
38237
  let stat2;
38174
38238
  try {
38175
38239
  stat2 = fs31.statSync(fullPath);
@@ -38205,7 +38269,7 @@ async function scanDocIndex(directory) {
38205
38269
  } catch {
38206
38270
  continue;
38207
38271
  }
38208
- const { title, summary } = extractTitleAndSummary(content, path42.basename(entry));
38272
+ const { title, summary } = extractTitleAndSummary(content, path43.basename(entry));
38209
38273
  const lineCount = content.split(`
38210
38274
  `).length;
38211
38275
  discoveredFiles.push({
@@ -38231,7 +38295,7 @@ async function scanDocIndex(directory) {
38231
38295
  files: discoveredFiles
38232
38296
  };
38233
38297
  try {
38234
- await mkdir6(path42.dirname(manifestPath), { recursive: true });
38298
+ await mkdir6(path43.dirname(manifestPath), { recursive: true });
38235
38299
  await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
38236
38300
  } catch {}
38237
38301
  return { manifest, cached: false };
@@ -38270,7 +38334,7 @@ function extractConstraintsFromContent(content) {
38270
38334
  return constraints;
38271
38335
  }
38272
38336
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
38273
- const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
38337
+ const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
38274
38338
  let manifest;
38275
38339
  try {
38276
38340
  const content = await readFile6(manifestPath, "utf-8");
@@ -38296,7 +38360,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
38296
38360
  }
38297
38361
  let fullContent;
38298
38362
  try {
38299
- fullContent = await readFile6(path42.join(directory, docFile.path), "utf-8");
38363
+ fullContent = await readFile6(path43.join(directory, docFile.path), "utf-8");
38300
38364
  } catch {
38301
38365
  skippedCount++;
38302
38366
  continue;
@@ -38319,7 +38383,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
38319
38383
  tier: "swarm",
38320
38384
  lesson: constraint,
38321
38385
  category: "architecture",
38322
- tags: ["doc-scan", path42.basename(docFile.path)],
38386
+ tags: ["doc-scan", path43.basename(docFile.path)],
38323
38387
  scope: "global",
38324
38388
  confidence: 0.5,
38325
38389
  status: "candidate",
@@ -38392,7 +38456,7 @@ var init_doc_scan = __esm(() => {
38392
38456
  }
38393
38457
  } catch {}
38394
38458
  if (force) {
38395
- const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
38459
+ const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
38396
38460
  try {
38397
38461
  fs31.unlinkSync(manifestPath);
38398
38462
  } catch {}
@@ -38447,9 +38511,9 @@ __export(exports_curator_drift, {
38447
38511
  buildDriftInjectionText: () => buildDriftInjectionText
38448
38512
  });
38449
38513
  import * as fs34 from "fs";
38450
- import * as path45 from "path";
38514
+ import * as path46 from "path";
38451
38515
  async function readPriorDriftReports(directory) {
38452
- const swarmDir = path45.join(directory, ".swarm");
38516
+ const swarmDir = path46.join(directory, ".swarm");
38453
38517
  const entries = await fs34.promises.readdir(swarmDir).catch(() => null);
38454
38518
  if (entries === null)
38455
38519
  return [];
@@ -38476,7 +38540,7 @@ async function readPriorDriftReports(directory) {
38476
38540
  async function writeDriftReport(directory, report) {
38477
38541
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
38478
38542
  const filePath = validateSwarmPath(directory, filename);
38479
- const swarmDir = path45.dirname(filePath);
38543
+ const swarmDir = path46.dirname(filePath);
38480
38544
  await fs34.promises.mkdir(swarmDir, { recursive: true });
38481
38545
  try {
38482
38546
  await fs34.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -40069,11 +40133,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
40069
40133
  throw toThrow;
40070
40134
  }, "quit_");
40071
40135
  var scriptDirectory = "";
40072
- function locateFile(path55) {
40136
+ function locateFile(path56) {
40073
40137
  if (Module["locateFile"]) {
40074
- return Module["locateFile"](path55, scriptDirectory);
40138
+ return Module["locateFile"](path56, scriptDirectory);
40075
40139
  }
40076
- return scriptDirectory + path55;
40140
+ return scriptDirectory + path56;
40077
40141
  }
40078
40142
  __name(locateFile, "locateFile");
40079
40143
  var readAsync, readBinary;
@@ -41813,13 +41877,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
41813
41877
  });
41814
41878
 
41815
41879
  // src/lang/runtime.ts
41816
- import * as path55 from "path";
41880
+ import * as path56 from "path";
41817
41881
  import { fileURLToPath as fileURLToPath2 } from "url";
41818
41882
  async function initTreeSitter() {
41819
41883
  if (treeSitterInitialized) {
41820
41884
  return;
41821
41885
  }
41822
- const thisDir = path55.dirname(fileURLToPath2(import.meta.url));
41886
+ const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
41823
41887
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
41824
41888
  if (isSource) {
41825
41889
  await Parser.init();
@@ -41827,7 +41891,7 @@ async function initTreeSitter() {
41827
41891
  const grammarsDir = getGrammarsDirAbsolute();
41828
41892
  await Parser.init({
41829
41893
  locateFile(scriptName) {
41830
- return path55.join(grammarsDir, scriptName);
41894
+ return path56.join(grammarsDir, scriptName);
41831
41895
  }
41832
41896
  });
41833
41897
  }
@@ -41848,9 +41912,9 @@ function getWasmFileName(languageId) {
41848
41912
  return `tree-sitter-${sanitized}.wasm`;
41849
41913
  }
41850
41914
  function getGrammarsDirAbsolute() {
41851
- const thisDir = path55.dirname(fileURLToPath2(import.meta.url));
41915
+ const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
41852
41916
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
41853
- return isSource ? path55.join(thisDir, "grammars") : path55.join(thisDir, "lang", "grammars");
41917
+ return isSource ? path56.join(thisDir, "grammars") : path56.join(thisDir, "lang", "grammars");
41854
41918
  }
41855
41919
  async function loadGrammar(languageId) {
41856
41920
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -41866,9 +41930,9 @@ async function loadGrammar(languageId) {
41866
41930
  await initTreeSitter();
41867
41931
  const parser = new Parser;
41868
41932
  const wasmFileName = getWasmFileName(normalizedId);
41869
- const wasmPath = path55.join(getGrammarsDirAbsolute(), wasmFileName);
41870
- const { existsSync: existsSync33 } = await import("fs");
41871
- if (!existsSync33(wasmPath)) {
41933
+ const wasmPath = path56.join(getGrammarsDirAbsolute(), wasmFileName);
41934
+ const { existsSync: existsSync34 } = await import("fs");
41935
+ if (!existsSync34(wasmPath)) {
41872
41936
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
41873
41937
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
41874
41938
  }
@@ -41913,7 +41977,7 @@ var init_runtime = __esm(() => {
41913
41977
  });
41914
41978
 
41915
41979
  // src/index.ts
41916
- import * as path73 from "path";
41980
+ import * as path74 from "path";
41917
41981
 
41918
41982
  // src/agents/index.ts
41919
41983
  init_config();
@@ -46021,8 +46085,9 @@ class PlanSyncWorker {
46021
46085
  try {
46022
46086
  log("[PlanSyncWorker] Syncing plan...");
46023
46087
  this.checkForUnauthorizedWrite();
46024
- const plan = await this.withTimeout(loadPlan(this.directory), this.syncTimeoutMs, "Sync operation timed out");
46088
+ const plan = await this.withTimeout(loadPlanJsonOnly(this.directory), this.syncTimeoutMs, "Sync operation timed out");
46025
46089
  if (plan) {
46090
+ await regeneratePlanMarkdown(this.directory, plan);
46026
46091
  log("[PlanSyncWorker] Sync complete", {
46027
46092
  title: plan.title,
46028
46093
  phase: plan.current_phase
@@ -46680,11 +46745,13 @@ async function handleClarifyCommand(_directory, args2) {
46680
46745
  // src/commands/close.ts
46681
46746
  init_schema();
46682
46747
  init_manager();
46748
+ import { execFileSync } from "child_process";
46683
46749
  import { promises as fs11 } from "fs";
46750
+ import path17 from "path";
46684
46751
 
46685
46752
  // src/hooks/knowledge-reader.ts
46686
46753
  init_knowledge_store();
46687
- import { existsSync as existsSync9 } from "fs";
46754
+ import { existsSync as existsSync10 } from "fs";
46688
46755
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
46689
46756
  import * as path13 from "path";
46690
46757
  var JACCARD_THRESHOLD = 0.6;
@@ -46737,7 +46804,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
46737
46804
  const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
46738
46805
  try {
46739
46806
  let shownData = {};
46740
- if (existsSync9(shownFile)) {
46807
+ if (existsSync10(shownFile)) {
46741
46808
  const content = await readFile3(shownFile, "utf-8");
46742
46809
  shownData = JSON.parse(content);
46743
46810
  }
@@ -46843,7 +46910,7 @@ async function readMergedKnowledge(directory, config3, context) {
46843
46910
  async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
46844
46911
  const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
46845
46912
  try {
46846
- if (!existsSync9(shownFile)) {
46913
+ if (!existsSync10(shownFile)) {
46847
46914
  return;
46848
46915
  }
46849
46916
  const content = await readFile3(shownFile, "utf-8");
@@ -48065,87 +48132,183 @@ var write_retro = createSwarmTool({
48065
48132
  });
48066
48133
 
48067
48134
  // src/commands/close.ts
48068
- async function handleCloseCommand(directory, _args) {
48135
+ async function handleCloseCommand(directory, args2) {
48069
48136
  const planPath = validateSwarmPath(directory, "plan.json");
48070
- let planData;
48137
+ let planExists = false;
48138
+ let planData = {
48139
+ title: path17.basename(directory) || "Ad-hoc session",
48140
+ phases: []
48141
+ };
48071
48142
  try {
48072
48143
  const content = await fs11.readFile(planPath, "utf-8");
48073
48144
  planData = JSON.parse(content);
48145
+ planExists = true;
48074
48146
  } catch (error93) {
48075
- return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
48147
+ if (error93?.code !== "ENOENT") {
48148
+ return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
48149
+ }
48150
+ const swarmDirExists = await fs11.access(path17.join(directory, ".swarm")).then(() => true).catch(() => false);
48151
+ if (!swarmDirExists) {
48152
+ return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
48153
+ }
48076
48154
  }
48077
48155
  const phases = planData.phases ?? [];
48078
48156
  const inProgressPhases = phases.filter((p) => p.status === "in_progress");
48079
- const allDone = phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
48080
- if (allDone) {
48081
- const closedCount = phases.filter((p) => p.status === "closed").length;
48082
- const blockedCount = phases.filter((p) => p.status === "blocked").length;
48083
- const completeCount = phases.filter((p) => p.status === "complete" || p.status === "completed").length;
48084
- return `\u2139\uFE0F Swarm already closed. ${completeCount} phases complete, ${closedCount} phases closed, ${blockedCount} phases blocked. No action taken.`;
48157
+ let planAlreadyDone = false;
48158
+ if (planExists) {
48159
+ planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
48085
48160
  }
48086
48161
  const config3 = KnowledgeConfigSchema.parse({});
48087
48162
  const projectName = planData.title ?? "Unknown Project";
48088
48163
  const closedPhases = [];
48089
48164
  const closedTasks = [];
48090
48165
  const warnings = [];
48091
- for (const phase of inProgressPhases) {
48092
- closedPhases.push(phase.id);
48093
- const retroResult = await executeWriteRetro({
48094
- phase: phase.id,
48095
- summary: "Phase closed via /swarm close",
48096
- task_count: Math.max(1, (phase.tasks ?? []).length),
48097
- task_complexity: "simple",
48098
- total_tool_calls: 0,
48099
- coder_revisions: 0,
48100
- reviewer_rejections: 0,
48101
- test_failures: 0,
48102
- security_findings: 0,
48103
- integration_issues: 0
48104
- }, directory);
48105
- try {
48106
- const parsed = JSON.parse(retroResult);
48107
- if (parsed.success !== true) {
48108
- warnings.push(`Retrospective write failed for phase ${phase.id}`);
48166
+ if (!planAlreadyDone) {
48167
+ for (const phase of inProgressPhases) {
48168
+ closedPhases.push(phase.id);
48169
+ let retroResult;
48170
+ try {
48171
+ retroResult = await executeWriteRetro({
48172
+ phase: phase.id,
48173
+ summary: "Phase closed via /swarm close",
48174
+ task_count: Math.max(1, (phase.tasks ?? []).length),
48175
+ task_complexity: "simple",
48176
+ total_tool_calls: 0,
48177
+ coder_revisions: 0,
48178
+ reviewer_rejections: 0,
48179
+ test_failures: 0,
48180
+ security_findings: 0,
48181
+ integration_issues: 0
48182
+ }, directory);
48183
+ } catch (retroError) {
48184
+ warnings.push(`Retrospective write threw for phase ${phase.id}: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
48185
+ }
48186
+ if (retroResult !== undefined) {
48187
+ try {
48188
+ const parsed = JSON.parse(retroResult);
48189
+ if (parsed.success !== true) {
48190
+ warnings.push(`Retrospective write failed for phase ${phase.id}`);
48191
+ }
48192
+ } catch {}
48109
48193
  }
48110
- } catch {}
48111
- for (const task of phase.tasks ?? []) {
48112
- if (task.status !== "completed" && task.status !== "complete") {
48113
- closedTasks.push(task.id);
48194
+ for (const task of phase.tasks ?? []) {
48195
+ if (task.status !== "completed" && task.status !== "complete") {
48196
+ closedTasks.push(task.id);
48197
+ }
48114
48198
  }
48115
48199
  }
48116
48200
  }
48201
+ const lessonsFilePath = path17.join(directory, ".swarm", "close-lessons.md");
48202
+ let explicitLessons = [];
48203
+ try {
48204
+ const lessonsText = await fs11.readFile(lessonsFilePath, "utf-8");
48205
+ explicitLessons = lessonsText.split(`
48206
+ `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
48207
+ } catch {}
48208
+ let curationSucceeded = false;
48117
48209
  try {
48118
- await curateAndStoreSwarm([], projectName, { phase_number: 0 }, directory, config3);
48210
+ await curateAndStoreSwarm(explicitLessons, projectName, { phase_number: 0 }, directory, config3);
48211
+ curationSucceeded = true;
48119
48212
  } catch (error93) {
48120
48213
  console.warn("[close-command] curateAndStoreSwarm error:", error93);
48121
48214
  }
48122
- for (const phase of phases) {
48123
- if (phase.status !== "complete" && phase.status !== "completed") {
48124
- phase.status = "closed";
48125
- if (!closedPhases.includes(phase.id)) {
48126
- closedPhases.push(phase.id);
48215
+ if (curationSucceeded && explicitLessons.length > 0) {
48216
+ await fs11.unlink(lessonsFilePath).catch(() => {});
48217
+ }
48218
+ if (planExists && !planAlreadyDone) {
48219
+ for (const phase of phases) {
48220
+ if (phase.status !== "complete" && phase.status !== "completed") {
48221
+ phase.status = "closed";
48222
+ if (!closedPhases.includes(phase.id)) {
48223
+ closedPhases.push(phase.id);
48224
+ }
48127
48225
  }
48128
- }
48129
- for (const task of phase.tasks ?? []) {
48130
- if (task.status !== "completed" && task.status !== "complete") {
48131
- task.status = "closed";
48132
- if (!closedTasks.includes(task.id)) {
48133
- closedTasks.push(task.id);
48226
+ for (const task of phase.tasks ?? []) {
48227
+ if (task.status !== "completed" && task.status !== "complete") {
48228
+ task.status = "closed";
48229
+ if (!closedTasks.includes(task.id)) {
48230
+ closedTasks.push(task.id);
48231
+ }
48134
48232
  }
48135
48233
  }
48136
48234
  }
48235
+ try {
48236
+ await fs11.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
48237
+ } catch (error93) {
48238
+ console.warn("[close-command] Failed to write plan.json:", error93);
48239
+ }
48137
48240
  }
48138
48241
  try {
48139
- await fs11.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
48242
+ await archiveEvidence(directory, 30, 10);
48140
48243
  } catch (error93) {
48141
- console.warn("[close-command] Failed to write plan.json:", error93);
48244
+ console.warn("[close-command] archiveEvidence error:", error93);
48142
48245
  }
48246
+ const swarmDir = path17.join(directory, ".swarm");
48247
+ let configBackupsRemoved = 0;
48143
48248
  try {
48144
- await archiveEvidence(directory, 30, 10);
48249
+ const swarmFiles = await fs11.readdir(swarmDir);
48250
+ const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
48251
+ for (const backup of configBackups) {
48252
+ try {
48253
+ await fs11.unlink(path17.join(swarmDir, backup));
48254
+ configBackupsRemoved++;
48255
+ } catch {}
48256
+ }
48257
+ } catch {}
48258
+ const contextPath = path17.join(directory, ".swarm", "context.md");
48259
+ const contextContent = [
48260
+ "# Context",
48261
+ "",
48262
+ "## Status",
48263
+ `Session closed after: ${projectName}`,
48264
+ `Closed: ${new Date().toISOString()}`,
48265
+ "No active plan. Next session starts fresh.",
48266
+ ""
48267
+ ].join(`
48268
+ `);
48269
+ try {
48270
+ await fs11.writeFile(contextPath, contextContent, "utf-8");
48145
48271
  } catch (error93) {
48146
- console.warn("[close-command] archiveEvidence error:", error93);
48272
+ console.warn("[close-command] Failed to write context.md:", error93);
48273
+ }
48274
+ const pruneBranches = args2.includes("--prune-branches");
48275
+ const prunedBranches = [];
48276
+ const pruneErrors = [];
48277
+ if (pruneBranches) {
48278
+ try {
48279
+ const branchOutput = execFileSync("git", ["branch", "-vv"], {
48280
+ cwd: directory,
48281
+ encoding: "utf-8",
48282
+ stdio: ["pipe", "pipe", "pipe"]
48283
+ });
48284
+ const goneBranches = branchOutput.split(`
48285
+ `).filter((line) => line.includes(": gone]")).map((line) => line.trim().replace(/^[*+]\s+/, "").split(/\s+/)[0]).filter(Boolean);
48286
+ for (const branch of goneBranches) {
48287
+ try {
48288
+ execFileSync("git", ["branch", "-d", branch], {
48289
+ cwd: directory,
48290
+ encoding: "utf-8",
48291
+ stdio: ["pipe", "pipe", "pipe"]
48292
+ });
48293
+ prunedBranches.push(branch);
48294
+ } catch {
48295
+ pruneErrors.push(branch);
48296
+ }
48297
+ }
48298
+ } catch {}
48147
48299
  }
48148
48300
  const closeSummaryPath = validateSwarmPath(directory, "close-summary.md");
48301
+ const actionsPerformed = [
48302
+ ...!planAlreadyDone && inProgressPhases.length > 0 ? ["- Wrote retrospectives for in-progress phases"] : [],
48303
+ "- Archived evidence bundles",
48304
+ "- Reset context.md for next session",
48305
+ ...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
48306
+ ...prunedBranches.length > 0 ? [
48307
+ `- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
48308
+ ] : [],
48309
+ "- Cleared agent sessions and delegation chains",
48310
+ ...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : []
48311
+ ];
48149
48312
  const summaryContent = [
48150
48313
  "# Swarm Close Summary",
48151
48314
  "",
@@ -48153,18 +48316,15 @@ async function handleCloseCommand(directory, _args) {
48153
48316
  `**Closed:** ${new Date().toISOString()}`,
48154
48317
  "",
48155
48318
  `## Phases Closed: ${closedPhases.length}`,
48156
- closedPhases.map((id) => `- Phase ${id}`).join(`
48157
- `),
48319
+ !planExists ? "_No plan \u2014 ad-hoc session_" : closedPhases.length > 0 ? closedPhases.map((id) => `- Phase ${id}`).join(`
48320
+ `) : "_No phases to close_",
48158
48321
  "",
48159
48322
  `## Tasks Closed: ${closedTasks.length}`,
48160
48323
  closedTasks.length > 0 ? closedTasks.map((id) => `- ${id}`).join(`
48161
48324
  `) : "_No incomplete tasks_",
48162
48325
  "",
48163
48326
  "## Actions Performed",
48164
- "- Wrote retrospectives for in-progress phases",
48165
- "- Archived evidence bundles",
48166
- "- Cleared agent sessions and delegation chains",
48167
- "- Set non-completed phases/tasks to closed status"
48327
+ ...actionsPerformed
48168
48328
  ].join(`
48169
48329
  `);
48170
48330
  try {
@@ -48180,21 +48340,27 @@ async function handleCloseCommand(directory, _args) {
48180
48340
  await writeCheckpoint(directory).catch(() => {});
48181
48341
  swarmState.agentSessions.clear();
48182
48342
  swarmState.delegationChains.clear();
48343
+ if (pruneErrors.length > 0) {
48344
+ warnings.push(`Could not prune ${pruneErrors.length} branch(es) (unmerged or checked out): ${pruneErrors.join(", ")}`);
48345
+ }
48183
48346
  const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
48347
+ if (planAlreadyDone) {
48348
+ return `\u2705 Session closed. Plan was already in a terminal state \u2014 cleanup steps applied.${warningMsg}`;
48349
+ }
48184
48350
  return `\u2705 Swarm closed successfully. ${closedPhases.length} phase(s) closed, ${closedTasks.length} incomplete task(s) marked closed.${warningMsg}`;
48185
48351
  }
48186
48352
 
48187
48353
  // src/commands/config.ts
48188
48354
  init_loader();
48189
48355
  import * as os4 from "os";
48190
- import * as path17 from "path";
48356
+ import * as path18 from "path";
48191
48357
  function getUserConfigDir2() {
48192
- return process.env.XDG_CONFIG_HOME || path17.join(os4.homedir(), ".config");
48358
+ return process.env.XDG_CONFIG_HOME || path18.join(os4.homedir(), ".config");
48193
48359
  }
48194
48360
  async function handleConfigCommand(directory, _args) {
48195
48361
  const config3 = loadPluginConfig(directory);
48196
- const userConfigPath = path17.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
48197
- const projectConfigPath = path17.join(directory, ".opencode", "opencode-swarm.json");
48362
+ const userConfigPath = path18.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
48363
+ const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
48198
48364
  const lines = [
48199
48365
  "## Swarm Configuration",
48200
48366
  "",
@@ -48217,7 +48383,7 @@ init_schema();
48217
48383
  // src/hooks/curator.ts
48218
48384
  import { randomUUID } from "crypto";
48219
48385
  import * as fs12 from "fs";
48220
- import * as path18 from "path";
48386
+ import * as path19 from "path";
48221
48387
  init_event_bus();
48222
48388
  init_manager2();
48223
48389
  init_knowledge_store();
@@ -48271,7 +48437,7 @@ async function readCuratorSummary(directory) {
48271
48437
  }
48272
48438
  async function writeCuratorSummary(directory, summary) {
48273
48439
  const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
48274
- fs12.mkdirSync(path18.dirname(resolvedPath), { recursive: true });
48440
+ fs12.mkdirSync(path19.dirname(resolvedPath), { recursive: true });
48275
48441
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
48276
48442
  await Bun.write(tempPath, JSON.stringify(summary, null, 2));
48277
48443
  fs12.renameSync(tempPath, resolvedPath);
@@ -48642,7 +48808,7 @@ ${phaseDigest.summary}`,
48642
48808
  };
48643
48809
  }
48644
48810
  await writeCuratorSummary(directory, updatedSummary);
48645
- const eventsPath = path18.join(directory, ".swarm", "events.jsonl");
48811
+ const eventsPath = path19.join(directory, ".swarm", "events.jsonl");
48646
48812
  for (const obs of complianceObservations) {
48647
48813
  await appendKnowledge(eventsPath, {
48648
48814
  type: "curator_compliance",
@@ -48784,7 +48950,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, _knowled
48784
48950
  created_at: now,
48785
48951
  updated_at: now,
48786
48952
  auto_generated: true,
48787
- project_name: path18.basename(directory)
48953
+ project_name: path19.basename(directory)
48788
48954
  };
48789
48955
  await appendKnowledge(knowledgePath, newEntry);
48790
48956
  applied++;
@@ -49002,7 +49168,7 @@ function formatCurationSummary(summary) {
49002
49168
  // src/commands/dark-matter.ts
49003
49169
  init_knowledge_store();
49004
49170
  init_co_change_analyzer();
49005
- import path20 from "path";
49171
+ import path21 from "path";
49006
49172
  async function handleDarkMatterCommand(directory, args2) {
49007
49173
  const options = {};
49008
49174
  for (let i2 = 0;i2 < args2.length; i2++) {
@@ -49024,7 +49190,7 @@ async function handleDarkMatterCommand(directory, args2) {
49024
49190
  const output = formatDarkMatterOutput(pairs);
49025
49191
  if (pairs.length > 0) {
49026
49192
  try {
49027
- const projectName = path20.basename(path20.resolve(directory));
49193
+ const projectName = path21.basename(path21.resolve(directory));
49028
49194
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
49029
49195
  if (entries.length > 0) {
49030
49196
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -49049,8 +49215,8 @@ init_manager();
49049
49215
  init_utils2();
49050
49216
  init_manager2();
49051
49217
  import * as child_process3 from "child_process";
49052
- import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
49053
- import path21 from "path";
49218
+ import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
49219
+ import path22 from "path";
49054
49220
  import { fileURLToPath } from "url";
49055
49221
  function validateTaskDag(plan) {
49056
49222
  const allTaskIds = new Set;
@@ -49283,7 +49449,7 @@ async function checkConfigBackups(directory) {
49283
49449
  }
49284
49450
  async function checkGitRepository(directory) {
49285
49451
  try {
49286
- if (!existsSync10(directory) || !statSync5(directory).isDirectory()) {
49452
+ if (!existsSync11(directory) || !statSync5(directory).isDirectory()) {
49287
49453
  return {
49288
49454
  name: "Git Repository",
49289
49455
  status: "\u274C",
@@ -49347,8 +49513,8 @@ async function checkSpecStaleness(directory, plan) {
49347
49513
  };
49348
49514
  }
49349
49515
  async function checkConfigParseability(directory) {
49350
- const configPath = path21.join(directory, ".opencode/opencode-swarm.json");
49351
- if (!existsSync10(configPath)) {
49516
+ const configPath = path22.join(directory, ".opencode/opencode-swarm.json");
49517
+ if (!existsSync11(configPath)) {
49352
49518
  return {
49353
49519
  name: "Config Parseability",
49354
49520
  status: "\u2705",
@@ -49394,15 +49560,15 @@ async function checkGrammarWasmFiles() {
49394
49560
  "tree-sitter-ini.wasm",
49395
49561
  "tree-sitter-regex.wasm"
49396
49562
  ];
49397
- const thisDir = path21.dirname(fileURLToPath(import.meta.url));
49563
+ const thisDir = path22.dirname(fileURLToPath(import.meta.url));
49398
49564
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
49399
- const grammarDir = isSource ? path21.join(thisDir, "..", "lang", "grammars") : path21.join(thisDir, "lang", "grammars");
49565
+ const grammarDir = isSource ? path22.join(thisDir, "..", "lang", "grammars") : path22.join(thisDir, "lang", "grammars");
49400
49566
  const missing = [];
49401
- if (!existsSync10(path21.join(grammarDir, "tree-sitter.wasm"))) {
49567
+ if (!existsSync11(path22.join(grammarDir, "tree-sitter.wasm"))) {
49402
49568
  missing.push("tree-sitter.wasm (core runtime)");
49403
49569
  }
49404
49570
  for (const file3 of grammarFiles) {
49405
- if (!existsSync10(path21.join(grammarDir, file3))) {
49571
+ if (!existsSync11(path22.join(grammarDir, file3))) {
49406
49572
  missing.push(file3);
49407
49573
  }
49408
49574
  }
@@ -49420,8 +49586,8 @@ async function checkGrammarWasmFiles() {
49420
49586
  };
49421
49587
  }
49422
49588
  async function checkCheckpointManifest(directory) {
49423
- const manifestPath = path21.join(directory, ".swarm/checkpoints.json");
49424
- if (!existsSync10(manifestPath)) {
49589
+ const manifestPath = path22.join(directory, ".swarm/checkpoints.json");
49590
+ if (!existsSync11(manifestPath)) {
49425
49591
  return {
49426
49592
  name: "Checkpoint Manifest",
49427
49593
  status: "\u2705",
@@ -49472,8 +49638,8 @@ async function checkCheckpointManifest(directory) {
49472
49638
  }
49473
49639
  }
49474
49640
  async function checkEventStreamIntegrity(directory) {
49475
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
49476
- if (!existsSync10(eventsPath)) {
49641
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
49642
+ if (!existsSync11(eventsPath)) {
49477
49643
  return {
49478
49644
  name: "Event Stream",
49479
49645
  status: "\u2705",
@@ -49513,8 +49679,8 @@ async function checkEventStreamIntegrity(directory) {
49513
49679
  }
49514
49680
  }
49515
49681
  async function checkSteeringDirectives(directory) {
49516
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
49517
- if (!existsSync10(eventsPath)) {
49682
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
49683
+ if (!existsSync11(eventsPath)) {
49518
49684
  return {
49519
49685
  name: "Steering Directives",
49520
49686
  status: "\u2705",
@@ -49569,8 +49735,8 @@ async function checkCurator(directory) {
49569
49735
  detail: "Disabled (enable via curator.enabled)"
49570
49736
  };
49571
49737
  }
49572
- const summaryPath = path21.join(directory, ".swarm/curator-summary.json");
49573
- if (!existsSync10(summaryPath)) {
49738
+ const summaryPath = path22.join(directory, ".swarm/curator-summary.json");
49739
+ if (!existsSync11(summaryPath)) {
49574
49740
  return {
49575
49741
  name: "Curator",
49576
49742
  status: "\u2705",
@@ -50469,14 +50635,14 @@ init_schema();
50469
50635
  // src/hooks/knowledge-migrator.ts
50470
50636
  init_knowledge_store();
50471
50637
  import { randomUUID as randomUUID3 } from "crypto";
50472
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
50638
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
50473
50639
  import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
50474
- import * as path23 from "path";
50640
+ import * as path24 from "path";
50475
50641
  async function migrateContextToKnowledge(directory, config3) {
50476
- const sentinelPath = path23.join(directory, ".swarm", ".knowledge-migrated");
50477
- const contextPath = path23.join(directory, ".swarm", "context.md");
50642
+ const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
50643
+ const contextPath = path24.join(directory, ".swarm", "context.md");
50478
50644
  const knowledgePath = resolveSwarmKnowledgePath(directory);
50479
- if (existsSync12(sentinelPath)) {
50645
+ if (existsSync13(sentinelPath)) {
50480
50646
  return {
50481
50647
  migrated: false,
50482
50648
  entriesMigrated: 0,
@@ -50485,7 +50651,7 @@ async function migrateContextToKnowledge(directory, config3) {
50485
50651
  skippedReason: "sentinel-exists"
50486
50652
  };
50487
50653
  }
50488
- if (!existsSync12(contextPath)) {
50654
+ if (!existsSync13(contextPath)) {
50489
50655
  return {
50490
50656
  migrated: false,
50491
50657
  entriesMigrated: 0,
@@ -50670,8 +50836,8 @@ function truncateLesson(text) {
50670
50836
  return `${text.slice(0, 277)}...`;
50671
50837
  }
50672
50838
  function inferProjectName(directory) {
50673
- const packageJsonPath = path23.join(directory, "package.json");
50674
- if (existsSync12(packageJsonPath)) {
50839
+ const packageJsonPath = path24.join(directory, "package.json");
50840
+ if (existsSync13(packageJsonPath)) {
50675
50841
  try {
50676
50842
  const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
50677
50843
  if (pkg.name && typeof pkg.name === "string") {
@@ -50679,7 +50845,7 @@ function inferProjectName(directory) {
50679
50845
  }
50680
50846
  } catch {}
50681
50847
  }
50682
- return path23.basename(directory);
50848
+ return path24.basename(directory);
50683
50849
  }
50684
50850
  async function writeSentinel(sentinelPath, migrated, dropped) {
50685
50851
  const sentinel = {
@@ -50691,7 +50857,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
50691
50857
  schema_version: 1,
50692
50858
  migration_tool: "knowledge-migrator.ts"
50693
50859
  };
50694
- await mkdir4(path23.dirname(sentinelPath), { recursive: true });
50860
+ await mkdir4(path24.dirname(sentinelPath), { recursive: true });
50695
50861
  await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
50696
50862
  }
50697
50863
 
@@ -50931,7 +51097,7 @@ init_preflight_service();
50931
51097
  // src/knowledge/hive-promoter.ts
50932
51098
  import * as fs20 from "fs";
50933
51099
  import * as os6 from "os";
50934
- import * as path30 from "path";
51100
+ import * as path31 from "path";
50935
51101
  var DANGEROUS_PATTERNS = [
50936
51102
  [/rm\s+-rf/, "rm\\s+-rf"],
50937
51103
  [/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
@@ -50977,13 +51143,13 @@ function getHiveFilePath() {
50977
51143
  const home = os6.homedir();
50978
51144
  let dataDir;
50979
51145
  if (platform === "win32") {
50980
- dataDir = path30.join(process.env.LOCALAPPDATA || path30.join(home, "AppData", "Local"), "opencode-swarm", "Data");
51146
+ dataDir = path31.join(process.env.LOCALAPPDATA || path31.join(home, "AppData", "Local"), "opencode-swarm", "Data");
50981
51147
  } else if (platform === "darwin") {
50982
- dataDir = path30.join(home, "Library", "Application Support", "opencode-swarm");
51148
+ dataDir = path31.join(home, "Library", "Application Support", "opencode-swarm");
50983
51149
  } else {
50984
- dataDir = path30.join(process.env.XDG_DATA_HOME || path30.join(home, ".local", "share"), "opencode-swarm");
51150
+ dataDir = path31.join(process.env.XDG_DATA_HOME || path31.join(home, ".local", "share"), "opencode-swarm");
50985
51151
  }
50986
- return path30.join(dataDir, "hive-knowledge.jsonl");
51152
+ return path31.join(dataDir, "hive-knowledge.jsonl");
50987
51153
  }
50988
51154
  async function promoteToHive(_directory, lesson, category) {
50989
51155
  const trimmed = (lesson ?? "").trim();
@@ -50995,7 +51161,7 @@ async function promoteToHive(_directory, lesson, category) {
50995
51161
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
50996
51162
  }
50997
51163
  const hivePath = getHiveFilePath();
50998
- const hiveDir = path30.dirname(hivePath);
51164
+ const hiveDir = path31.dirname(hivePath);
50999
51165
  if (!fs20.existsSync(hiveDir)) {
51000
51166
  fs20.mkdirSync(hiveDir, { recursive: true });
51001
51167
  }
@@ -51017,7 +51183,7 @@ async function promoteToHive(_directory, lesson, category) {
51017
51183
  return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
51018
51184
  }
51019
51185
  async function promoteFromSwarm(directory, lessonId) {
51020
- const knowledgePath = path30.join(directory, ".swarm", "knowledge.jsonl");
51186
+ const knowledgePath = path31.join(directory, ".swarm", "knowledge.jsonl");
51021
51187
  const entries = [];
51022
51188
  if (fs20.existsSync(knowledgePath)) {
51023
51189
  const content = fs20.readFileSync(knowledgePath, "utf-8");
@@ -51044,7 +51210,7 @@ async function promoteFromSwarm(directory, lessonId) {
51044
51210
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
51045
51211
  }
51046
51212
  const hivePath = getHiveFilePath();
51047
- const hiveDir = path30.dirname(hivePath);
51213
+ const hiveDir = path31.dirname(hivePath);
51048
51214
  if (!fs20.existsSync(hiveDir)) {
51049
51215
  fs20.mkdirSync(hiveDir, { recursive: true });
51050
51216
  }
@@ -51175,7 +51341,7 @@ async function handleResetCommand(directory, args2) {
51175
51341
  // src/commands/reset-session.ts
51176
51342
  init_utils2();
51177
51343
  import * as fs22 from "fs";
51178
- import * as path31 from "path";
51344
+ import * as path32 from "path";
51179
51345
  async function handleResetSessionCommand(directory, _args) {
51180
51346
  const results = [];
51181
51347
  try {
@@ -51190,13 +51356,13 @@ async function handleResetSessionCommand(directory, _args) {
51190
51356
  results.push("\u274C Failed to delete state.json");
51191
51357
  }
51192
51358
  try {
51193
- const sessionDir = path31.dirname(validateSwarmPath(directory, "session/state.json"));
51359
+ const sessionDir = path32.dirname(validateSwarmPath(directory, "session/state.json"));
51194
51360
  if (fs22.existsSync(sessionDir)) {
51195
51361
  const files = fs22.readdirSync(sessionDir);
51196
51362
  const otherFiles = files.filter((f) => f !== "state.json");
51197
51363
  let deletedCount = 0;
51198
51364
  for (const file3 of otherFiles) {
51199
- const filePath = path31.join(sessionDir, file3);
51365
+ const filePath = path32.join(sessionDir, file3);
51200
51366
  if (fs22.lstatSync(filePath).isFile()) {
51201
51367
  fs22.unlinkSync(filePath);
51202
51368
  deletedCount++;
@@ -51227,7 +51393,7 @@ async function handleResetSessionCommand(directory, _args) {
51227
51393
  init_utils2();
51228
51394
  init_utils();
51229
51395
  import { mkdirSync as mkdirSync11, readdirSync as readdirSync8, renameSync as renameSync8, rmSync as rmSync3, statSync as statSync8 } from "fs";
51230
- import * as path32 from "path";
51396
+ import * as path33 from "path";
51231
51397
  var SUMMARY_ID_REGEX = /^S\d+$/;
51232
51398
  function sanitizeSummaryId(id) {
51233
51399
  if (!id || id.length === 0) {
@@ -51262,9 +51428,9 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
51262
51428
  if (serializedSize > maxStoredBytes) {
51263
51429
  throw new Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);
51264
51430
  }
51265
- const relativePath = path32.join("summaries", `${sanitizedId}.json`);
51431
+ const relativePath = path33.join("summaries", `${sanitizedId}.json`);
51266
51432
  const summaryPath = validateSwarmPath(directory, relativePath);
51267
- const summaryDir = path32.dirname(summaryPath);
51433
+ const summaryDir = path33.dirname(summaryPath);
51268
51434
  const entry = {
51269
51435
  id: sanitizedId,
51270
51436
  summaryText,
@@ -51274,7 +51440,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
51274
51440
  };
51275
51441
  const entryJson = JSON.stringify(entry);
51276
51442
  mkdirSync11(summaryDir, { recursive: true });
51277
- const tempPath = path32.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
51443
+ const tempPath = path33.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
51278
51444
  try {
51279
51445
  await Bun.write(tempPath, entryJson);
51280
51446
  renameSync8(tempPath, summaryPath);
@@ -51287,7 +51453,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
51287
51453
  }
51288
51454
  async function loadFullOutput(directory, id) {
51289
51455
  const sanitizedId = sanitizeSummaryId(id);
51290
- const relativePath = path32.join("summaries", `${sanitizedId}.json`);
51456
+ const relativePath = path33.join("summaries", `${sanitizedId}.json`);
51291
51457
  validateSwarmPath(directory, relativePath);
51292
51458
  const content = await readSwarmFileAsync(directory, relativePath);
51293
51459
  if (content === null) {
@@ -51341,7 +51507,7 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
51341
51507
  // src/commands/rollback.ts
51342
51508
  init_utils2();
51343
51509
  import * as fs23 from "fs";
51344
- import * as path33 from "path";
51510
+ import * as path34 from "path";
51345
51511
  async function handleRollbackCommand(directory, args2) {
51346
51512
  const phaseArg = args2[0];
51347
51513
  if (!phaseArg) {
@@ -51399,8 +51565,8 @@ async function handleRollbackCommand(directory, args2) {
51399
51565
  const successes = [];
51400
51566
  const failures = [];
51401
51567
  for (const file3 of checkpointFiles) {
51402
- const src = path33.join(checkpointDir, file3);
51403
- const dest = path33.join(swarmDir, file3);
51568
+ const src = path34.join(checkpointDir, file3);
51569
+ const dest = path34.join(swarmDir, file3);
51404
51570
  try {
51405
51571
  fs23.cpSync(src, dest, { recursive: true, force: true });
51406
51572
  successes.push(file3);
@@ -51464,9 +51630,9 @@ async function handleSimulateCommand(directory, args2) {
51464
51630
  const report = reportLines.filter(Boolean).join(`
51465
51631
  `);
51466
51632
  const fs24 = await import("fs/promises");
51467
- const path34 = await import("path");
51468
- const reportPath = path34.join(directory, ".swarm", "simulate-report.md");
51469
- await fs24.mkdir(path34.dirname(reportPath), { recursive: true });
51633
+ const path35 = await import("path");
51634
+ const reportPath = path35.join(directory, ".swarm", "simulate-report.md");
51635
+ await fs24.mkdir(path35.dirname(reportPath), { recursive: true });
51470
51636
  await fs24.writeFile(reportPath, report, "utf-8");
51471
51637
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
51472
51638
  }
@@ -51825,7 +51991,7 @@ init_manager2();
51825
51991
 
51826
51992
  // src/services/compaction-service.ts
51827
51993
  import * as fs24 from "fs";
51828
- import * as path34 from "path";
51994
+ import * as path35 from "path";
51829
51995
  function makeInitialState() {
51830
51996
  return {
51831
51997
  lastObservationAt: 0,
@@ -51848,7 +52014,7 @@ function getSessionState(sessionId) {
51848
52014
  }
51849
52015
  function appendSnapshot(directory, tier, budgetPct, message) {
51850
52016
  try {
51851
- const snapshotPath = path34.join(directory, ".swarm", "context-snapshot.md");
52017
+ const snapshotPath = path35.join(directory, ".swarm", "context-snapshot.md");
51852
52018
  const timestamp = new Date().toISOString();
51853
52019
  const entry = `
51854
52020
  ## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
@@ -52579,11 +52745,11 @@ async function doFlush(directory) {
52579
52745
  const activitySection = renderActivitySection();
52580
52746
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
52581
52747
  const flushedCount = swarmState.pendingEvents;
52582
- const path35 = nodePath2.join(directory, ".swarm", "context.md");
52583
- const tempPath = `${path35}.tmp`;
52748
+ const path36 = nodePath2.join(directory, ".swarm", "context.md");
52749
+ const tempPath = `${path36}.tmp`;
52584
52750
  try {
52585
52751
  await Bun.write(tempPath, updated);
52586
- renameSync9(tempPath, path35);
52752
+ renameSync9(tempPath, path36);
52587
52753
  } catch (writeError) {
52588
52754
  try {
52589
52755
  unlinkSync4(tempPath);
@@ -53260,7 +53426,7 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
53260
53426
  // src/hooks/delegation-gate.ts
53261
53427
  init_schema();
53262
53428
  import * as fs26 from "fs";
53263
- import * as path37 from "path";
53429
+ import * as path38 from "path";
53264
53430
 
53265
53431
  // src/parallel/review-router.ts
53266
53432
  async function computeComplexity(directory, changedFiles) {
@@ -53273,8 +53439,8 @@ async function computeComplexity(directory, changedFiles) {
53273
53439
  }
53274
53440
  try {
53275
53441
  const fs26 = await import("fs");
53276
- const path35 = await import("path");
53277
- const filePath = path35.join(directory, file3);
53442
+ const path36 = await import("path");
53443
+ const filePath = path36.join(directory, file3);
53278
53444
  if (!fs26.existsSync(filePath)) {
53279
53445
  continue;
53280
53446
  }
@@ -53326,7 +53492,7 @@ function shouldParallelizeReview(routing) {
53326
53492
  init_telemetry();
53327
53493
 
53328
53494
  // src/hooks/guardrails.ts
53329
- import * as path35 from "path";
53495
+ import * as path36 from "path";
53330
53496
  init_constants();
53331
53497
  init_schema();
53332
53498
 
@@ -53490,10 +53656,10 @@ function isArchitect(sessionId) {
53490
53656
  function isOutsideSwarmDir(filePath, directory) {
53491
53657
  if (!filePath)
53492
53658
  return false;
53493
- const swarmDir = path35.resolve(directory, ".swarm");
53494
- const resolved = path35.resolve(directory, filePath);
53495
- const relative5 = path35.relative(swarmDir, resolved);
53496
- return relative5.startsWith("..") || path35.isAbsolute(relative5);
53659
+ const swarmDir = path36.resolve(directory, ".swarm");
53660
+ const resolved = path36.resolve(directory, filePath);
53661
+ const relative5 = path36.relative(swarmDir, resolved);
53662
+ return relative5.startsWith("..") || path36.isAbsolute(relative5);
53497
53663
  }
53498
53664
  function isSourceCodePath(filePath) {
53499
53665
  if (!filePath)
@@ -53561,13 +53727,13 @@ function getCurrentTaskId(sessionId) {
53561
53727
  }
53562
53728
  function isInDeclaredScope(filePath, scopeEntries, cwd) {
53563
53729
  const dir = cwd ?? process.cwd();
53564
- const resolvedFile = path35.resolve(dir, filePath);
53730
+ const resolvedFile = path36.resolve(dir, filePath);
53565
53731
  return scopeEntries.some((scope) => {
53566
- const resolvedScope = path35.resolve(dir, scope);
53732
+ const resolvedScope = path36.resolve(dir, scope);
53567
53733
  if (resolvedFile === resolvedScope)
53568
53734
  return true;
53569
- const rel = path35.relative(resolvedScope, resolvedFile);
53570
- return rel.length > 0 && !rel.startsWith("..") && !path35.isAbsolute(rel);
53735
+ const rel = path36.relative(resolvedScope, resolvedFile);
53736
+ return rel.length > 0 && !rel.startsWith("..") && !path36.isAbsolute(rel);
53571
53737
  });
53572
53738
  }
53573
53739
  function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
@@ -53826,18 +53992,18 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
53826
53992
  const toolArgs = args2;
53827
53993
  const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
53828
53994
  if (typeof targetPath === "string" && targetPath.length > 0) {
53829
- const resolvedTarget = path35.resolve(effectiveDirectory, targetPath).toLowerCase();
53830
- const planMdPath = path35.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
53831
- const planJsonPath = path35.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
53995
+ const resolvedTarget = path36.resolve(effectiveDirectory, targetPath).toLowerCase();
53996
+ const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
53997
+ const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
53832
53998
  if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
53833
53999
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
53834
54000
  }
53835
54001
  }
53836
54002
  if (!targetPath && (tool3 === "apply_patch" || tool3 === "patch")) {
53837
54003
  for (const p of extractPatchTargetPaths(tool3, args2)) {
53838
- const resolvedP = path35.resolve(effectiveDirectory, p);
53839
- const planMdPath = path35.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
53840
- const planJsonPath = path35.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
54004
+ const resolvedP = path36.resolve(effectiveDirectory, p);
54005
+ const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
54006
+ const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
53841
54007
  if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
53842
54008
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
53843
54009
  }
@@ -53856,7 +54022,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
53856
54022
  }
53857
54023
  }
53858
54024
  }
53859
- if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path35.relative(effectiveDirectory, path35.resolve(effectiveDirectory, targetPath)))) {
54025
+ if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path36.relative(effectiveDirectory, path36.resolve(effectiveDirectory, targetPath)))) {
53860
54026
  const session = swarmState.agentSessions.get(sessionID);
53861
54027
  if (session) {
53862
54028
  session.architectWriteCount++;
@@ -54531,8 +54697,8 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules) {
54531
54697
  const normalizedAgent = agentName.toLowerCase();
54532
54698
  const strippedAgent = stripKnownSwarmPrefix(agentName).toLowerCase();
54533
54699
  const dir = cwd || process.cwd();
54534
- const resolved = path35.resolve(dir, filePath);
54535
- const normalizedPath = path35.relative(dir, resolved).replace(/\\/g, "/");
54700
+ const resolved = path36.resolve(dir, filePath);
54701
+ const normalizedPath = path36.relative(dir, resolved).replace(/\\/g, "/");
54536
54702
  const rules = effectiveRules[normalizedAgent] ?? effectiveRules[strippedAgent];
54537
54703
  if (!rules) {
54538
54704
  return { allowed: false, reason: `Unknown agent: ${agentName}` };
@@ -54614,10 +54780,10 @@ async function getEvidenceTaskId(session, directory) {
54614
54780
  if (typeof directory !== "string" || directory.length === 0) {
54615
54781
  return null;
54616
54782
  }
54617
- const resolvedDirectory = path37.resolve(directory);
54618
- const planPath = path37.join(resolvedDirectory, ".swarm", "plan.json");
54619
- const resolvedPlanPath = path37.resolve(planPath);
54620
- if (!resolvedPlanPath.startsWith(resolvedDirectory + path37.sep) && resolvedPlanPath !== resolvedDirectory) {
54783
+ const resolvedDirectory = path38.resolve(directory);
54784
+ const planPath = path38.join(resolvedDirectory, ".swarm", "plan.json");
54785
+ const resolvedPlanPath = path38.resolve(planPath);
54786
+ if (!resolvedPlanPath.startsWith(resolvedDirectory + path38.sep) && resolvedPlanPath !== resolvedDirectory) {
54621
54787
  return null;
54622
54788
  }
54623
54789
  const planContent = await fs26.promises.readFile(resolvedPlanPath, "utf-8");
@@ -55345,7 +55511,7 @@ function consolidateSystemMessages(messages) {
55345
55511
  // src/hooks/phase-monitor.ts
55346
55512
  init_schema();
55347
55513
  init_manager2();
55348
- import * as path39 from "path";
55514
+ import * as path40 from "path";
55349
55515
  init_utils2();
55350
55516
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
55351
55517
  let lastKnownPhase = null;
@@ -55366,9 +55532,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
55366
55532
  const llmDelegate = delegateFactory?.(sessionId);
55367
55533
  const initResult = await runner(directory, curatorConfig, llmDelegate);
55368
55534
  if (initResult.briefing) {
55369
- const briefingPath = path39.join(directory, ".swarm", "curator-briefing.md");
55535
+ const briefingPath = path40.join(directory, ".swarm", "curator-briefing.md");
55370
55536
  const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
55371
- await mkdir5(path39.dirname(briefingPath), { recursive: true });
55537
+ await mkdir5(path40.dirname(briefingPath), { recursive: true });
55372
55538
  await writeFile5(briefingPath, initResult.briefing, "utf-8");
55373
55539
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
55374
55540
  const initReceipt = buildApprovedReceipt2({
@@ -55502,14 +55668,14 @@ init_manager();
55502
55668
  init_detector();
55503
55669
  init_manager2();
55504
55670
  import * as fs32 from "fs";
55505
- import * as path43 from "path";
55671
+ import * as path44 from "path";
55506
55672
 
55507
55673
  // src/services/decision-drift-analyzer.ts
55508
55674
  init_utils2();
55509
55675
  init_manager2();
55510
55676
  init_utils();
55511
55677
  import * as fs29 from "fs";
55512
- import * as path40 from "path";
55678
+ import * as path41 from "path";
55513
55679
  var DEFAULT_DRIFT_CONFIG = {
55514
55680
  staleThresholdPhases: 1,
55515
55681
  detectContradictions: true,
@@ -55663,7 +55829,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
55663
55829
  currentPhase = legacyPhase;
55664
55830
  }
55665
55831
  }
55666
- const contextPath = path40.join(directory, ".swarm", "context.md");
55832
+ const contextPath = path41.join(directory, ".swarm", "context.md");
55667
55833
  let contextContent = "";
55668
55834
  try {
55669
55835
  if (fs29.existsSync(contextPath)) {
@@ -55793,7 +55959,7 @@ init_utils();
55793
55959
  init_constants();
55794
55960
  init_schema();
55795
55961
  import * as fs30 from "fs/promises";
55796
- import * as path41 from "path";
55962
+ import * as path42 from "path";
55797
55963
  function safeGet(obj, key) {
55798
55964
  if (!obj || !Object.hasOwn(obj, key))
55799
55965
  return;
@@ -56007,9 +56173,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
56007
56173
  let eventLogged = false;
56008
56174
  let checkpointCreated = false;
56009
56175
  try {
56010
- const swarmDir = path41.join(directory, ".swarm");
56176
+ const swarmDir = path42.join(directory, ".swarm");
56011
56177
  await fs30.mkdir(swarmDir, { recursive: true });
56012
- const eventsPath = path41.join(swarmDir, "events.jsonl");
56178
+ const eventsPath = path42.join(swarmDir, "events.jsonl");
56013
56179
  await fs30.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
56014
56180
  `);
56015
56181
  eventLogged = true;
@@ -56406,7 +56572,7 @@ function createSystemEnhancerHook(config3, directory) {
56406
56572
  await fs32.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
56407
56573
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
56408
56574
  try {
56409
- const projectName = path43.basename(path43.resolve(directory));
56575
+ const projectName = path44.basename(path44.resolve(directory));
56410
56576
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
56411
56577
  const knowledgePath = resolveSwarmKnowledgePath(directory);
56412
56578
  const existingEntries = await readKnowledge(knowledgePath);
@@ -57530,7 +57696,7 @@ function isReadTool(toolName) {
57530
57696
 
57531
57697
  // src/hooks/incremental-verify.ts
57532
57698
  import * as fs33 from "fs";
57533
- import * as path44 from "path";
57699
+ import * as path45 from "path";
57534
57700
 
57535
57701
  // src/hooks/spawn-helper.ts
57536
57702
  import * as child_process4 from "child_process";
@@ -57608,18 +57774,18 @@ function spawnAsync(command, cwd, timeoutMs) {
57608
57774
  // src/hooks/incremental-verify.ts
57609
57775
  var emittedSkipAdvisories = new Set;
57610
57776
  function detectPackageManager(projectDir) {
57611
- if (fs33.existsSync(path44.join(projectDir, "bun.lockb")))
57777
+ if (fs33.existsSync(path45.join(projectDir, "bun.lockb")))
57612
57778
  return "bun";
57613
- if (fs33.existsSync(path44.join(projectDir, "pnpm-lock.yaml")))
57779
+ if (fs33.existsSync(path45.join(projectDir, "pnpm-lock.yaml")))
57614
57780
  return "pnpm";
57615
- if (fs33.existsSync(path44.join(projectDir, "yarn.lock")))
57781
+ if (fs33.existsSync(path45.join(projectDir, "yarn.lock")))
57616
57782
  return "yarn";
57617
- if (fs33.existsSync(path44.join(projectDir, "package-lock.json")))
57783
+ if (fs33.existsSync(path45.join(projectDir, "package-lock.json")))
57618
57784
  return "npm";
57619
57785
  return "bun";
57620
57786
  }
57621
57787
  function detectTypecheckCommand(projectDir) {
57622
- const pkgPath = path44.join(projectDir, "package.json");
57788
+ const pkgPath = path45.join(projectDir, "package.json");
57623
57789
  if (fs33.existsSync(pkgPath)) {
57624
57790
  try {
57625
57791
  const pkg = JSON.parse(fs33.readFileSync(pkgPath, "utf8"));
@@ -57636,8 +57802,8 @@ function detectTypecheckCommand(projectDir) {
57636
57802
  ...pkg.dependencies,
57637
57803
  ...pkg.devDependencies
57638
57804
  };
57639
- if (!deps?.typescript && !fs33.existsSync(path44.join(projectDir, "tsconfig.json"))) {}
57640
- const hasTSMarkers = deps?.typescript || fs33.existsSync(path44.join(projectDir, "tsconfig.json"));
57805
+ if (!deps?.typescript && !fs33.existsSync(path45.join(projectDir, "tsconfig.json"))) {}
57806
+ const hasTSMarkers = deps?.typescript || fs33.existsSync(path45.join(projectDir, "tsconfig.json"));
57641
57807
  if (hasTSMarkers) {
57642
57808
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
57643
57809
  }
@@ -57645,13 +57811,13 @@ function detectTypecheckCommand(projectDir) {
57645
57811
  return null;
57646
57812
  }
57647
57813
  }
57648
- if (fs33.existsSync(path44.join(projectDir, "go.mod"))) {
57814
+ if (fs33.existsSync(path45.join(projectDir, "go.mod"))) {
57649
57815
  return { command: ["go", "vet", "./..."], language: "go" };
57650
57816
  }
57651
- if (fs33.existsSync(path44.join(projectDir, "Cargo.toml"))) {
57817
+ if (fs33.existsSync(path45.join(projectDir, "Cargo.toml"))) {
57652
57818
  return { command: ["cargo", "check"], language: "rust" };
57653
57819
  }
57654
- if (fs33.existsSync(path44.join(projectDir, "pyproject.toml")) || fs33.existsSync(path44.join(projectDir, "requirements.txt")) || fs33.existsSync(path44.join(projectDir, "setup.py"))) {
57820
+ if (fs33.existsSync(path45.join(projectDir, "pyproject.toml")) || fs33.existsSync(path45.join(projectDir, "requirements.txt")) || fs33.existsSync(path45.join(projectDir, "setup.py"))) {
57655
57821
  return { command: null, language: "python" };
57656
57822
  }
57657
57823
  try {
@@ -57952,7 +58118,7 @@ ${injectionText}`;
57952
58118
  // src/hooks/scope-guard.ts
57953
58119
  init_constants();
57954
58120
  init_schema();
57955
- import * as path46 from "path";
58121
+ import * as path47 from "path";
57956
58122
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
57957
58123
  function createScopeGuardHook(config3, directory, injectAdvisory) {
57958
58124
  const enabled = config3.enabled ?? true;
@@ -58004,13 +58170,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
58004
58170
  }
58005
58171
  function isFileInScope(filePath, scopeEntries, directory) {
58006
58172
  const dir = directory ?? process.cwd();
58007
- const resolvedFile = path46.resolve(dir, filePath);
58173
+ const resolvedFile = path47.resolve(dir, filePath);
58008
58174
  return scopeEntries.some((scope) => {
58009
- const resolvedScope = path46.resolve(dir, scope);
58175
+ const resolvedScope = path47.resolve(dir, scope);
58010
58176
  if (resolvedFile === resolvedScope)
58011
58177
  return true;
58012
- const rel = path46.relative(resolvedScope, resolvedFile);
58013
- return rel.length > 0 && !rel.startsWith("..") && !path46.isAbsolute(rel);
58178
+ const rel = path47.relative(resolvedScope, resolvedFile);
58179
+ return rel.length > 0 && !rel.startsWith("..") && !path47.isAbsolute(rel);
58014
58180
  });
58015
58181
  }
58016
58182
 
@@ -58060,7 +58226,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
58060
58226
 
58061
58227
  // src/hooks/slop-detector.ts
58062
58228
  import * as fs35 from "fs";
58063
- import * as path47 from "path";
58229
+ import * as path48 from "path";
58064
58230
  var WRITE_EDIT_TOOLS = new Set([
58065
58231
  "write",
58066
58232
  "edit",
@@ -58110,7 +58276,7 @@ function walkFiles(dir, exts, deadline) {
58110
58276
  break;
58111
58277
  if (entry.isSymbolicLink())
58112
58278
  continue;
58113
- const full = path47.join(dir, entry.name);
58279
+ const full = path48.join(dir, entry.name);
58114
58280
  if (entry.isDirectory()) {
58115
58281
  if (entry.name === "node_modules" || entry.name === ".git")
58116
58282
  continue;
@@ -58125,7 +58291,7 @@ function walkFiles(dir, exts, deadline) {
58125
58291
  return results;
58126
58292
  }
58127
58293
  function checkDeadExports(content, projectDir, startTime) {
58128
- const hasPackageJson = fs35.existsSync(path47.join(projectDir, "package.json"));
58294
+ const hasPackageJson = fs35.existsSync(path48.join(projectDir, "package.json"));
58129
58295
  if (!hasPackageJson)
58130
58296
  return null;
58131
58297
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -58528,13 +58694,13 @@ init_telemetry();
58528
58694
  init_tool();
58529
58695
  init_create_tool();
58530
58696
  import * as fs38 from "fs";
58531
- import * as path49 from "path";
58697
+ import * as path50 from "path";
58532
58698
 
58533
58699
  // src/tools/symbols.ts
58534
58700
  init_tool();
58535
58701
  init_create_tool();
58536
58702
  import * as fs37 from "fs";
58537
- import * as path48 from "path";
58703
+ import * as path49 from "path";
58538
58704
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
58539
58705
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
58540
58706
  function containsWindowsAttacks(str) {
@@ -58551,11 +58717,11 @@ function containsWindowsAttacks(str) {
58551
58717
  }
58552
58718
  function isPathInWorkspace(filePath, workspace) {
58553
58719
  try {
58554
- const resolvedPath = path48.resolve(workspace, filePath);
58720
+ const resolvedPath = path49.resolve(workspace, filePath);
58555
58721
  const realWorkspace = fs37.realpathSync(workspace);
58556
58722
  const realResolvedPath = fs37.realpathSync(resolvedPath);
58557
- const relativePath = path48.relative(realWorkspace, realResolvedPath);
58558
- if (relativePath.startsWith("..") || path48.isAbsolute(relativePath)) {
58723
+ const relativePath = path49.relative(realWorkspace, realResolvedPath);
58724
+ if (relativePath.startsWith("..") || path49.isAbsolute(relativePath)) {
58559
58725
  return false;
58560
58726
  }
58561
58727
  return true;
@@ -58567,7 +58733,7 @@ function validatePathForRead(filePath, workspace) {
58567
58733
  return isPathInWorkspace(filePath, workspace);
58568
58734
  }
58569
58735
  function extractTSSymbols(filePath, cwd) {
58570
- const fullPath = path48.join(cwd, filePath);
58736
+ const fullPath = path49.join(cwd, filePath);
58571
58737
  if (!validatePathForRead(fullPath, cwd)) {
58572
58738
  return [];
58573
58739
  }
@@ -58719,7 +58885,7 @@ function extractTSSymbols(filePath, cwd) {
58719
58885
  });
58720
58886
  }
58721
58887
  function extractPythonSymbols(filePath, cwd) {
58722
- const fullPath = path48.join(cwd, filePath);
58888
+ const fullPath = path49.join(cwd, filePath);
58723
58889
  if (!validatePathForRead(fullPath, cwd)) {
58724
58890
  return [];
58725
58891
  }
@@ -58802,7 +58968,7 @@ var symbols = createSwarmTool({
58802
58968
  }, null, 2);
58803
58969
  }
58804
58970
  const cwd = directory;
58805
- const ext = path48.extname(file3);
58971
+ const ext = path49.extname(file3);
58806
58972
  if (containsControlChars(file3)) {
58807
58973
  return JSON.stringify({
58808
58974
  file: file3,
@@ -58878,14 +59044,14 @@ function containsWindowsAttacks2(str) {
58878
59044
  }
58879
59045
  function isPathInWorkspace2(filePath, workspace) {
58880
59046
  try {
58881
- const resolvedPath = path49.resolve(workspace, filePath);
59047
+ const resolvedPath = path50.resolve(workspace, filePath);
58882
59048
  if (!fs38.existsSync(resolvedPath)) {
58883
59049
  return true;
58884
59050
  }
58885
59051
  const realWorkspace = fs38.realpathSync(workspace);
58886
59052
  const realResolvedPath = fs38.realpathSync(resolvedPath);
58887
- const relativePath = path49.relative(realWorkspace, realResolvedPath);
58888
- if (relativePath.startsWith("..") || path49.isAbsolute(relativePath)) {
59053
+ const relativePath = path50.relative(realWorkspace, realResolvedPath);
59054
+ if (relativePath.startsWith("..") || path50.isAbsolute(relativePath)) {
58889
59055
  return false;
58890
59056
  }
58891
59057
  return true;
@@ -58894,7 +59060,7 @@ function isPathInWorkspace2(filePath, workspace) {
58894
59060
  }
58895
59061
  }
58896
59062
  function processFile(file3, cwd, exportedOnly) {
58897
- const ext = path49.extname(file3);
59063
+ const ext = path50.extname(file3);
58898
59064
  if (containsControlChars(file3)) {
58899
59065
  return {
58900
59066
  file: file3,
@@ -58927,7 +59093,7 @@ function processFile(file3, cwd, exportedOnly) {
58927
59093
  errorType: "path-outside-workspace"
58928
59094
  };
58929
59095
  }
58930
- const fullPath = path49.join(cwd, file3);
59096
+ const fullPath = path50.join(cwd, file3);
58931
59097
  if (!fs38.existsSync(fullPath)) {
58932
59098
  return {
58933
59099
  file: file3,
@@ -59218,7 +59384,7 @@ init_manager();
59218
59384
  init_create_tool();
59219
59385
  init_resolve_working_directory();
59220
59386
  import * as fs39 from "fs";
59221
- import * as path50 from "path";
59387
+ import * as path51 from "path";
59222
59388
  var EVIDENCE_DIR = ".swarm/evidence";
59223
59389
  var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
59224
59390
  function isValidTaskId3(taskId) {
@@ -59235,9 +59401,9 @@ function isValidTaskId3(taskId) {
59235
59401
  return TASK_ID_PATTERN2.test(taskId);
59236
59402
  }
59237
59403
  function isPathWithinSwarm(filePath, workspaceRoot) {
59238
- const normalizedWorkspace = path50.resolve(workspaceRoot);
59239
- const swarmPath = path50.join(normalizedWorkspace, ".swarm", "evidence");
59240
- const normalizedPath = path50.resolve(filePath);
59404
+ const normalizedWorkspace = path51.resolve(workspaceRoot);
59405
+ const swarmPath = path51.join(normalizedWorkspace, ".swarm", "evidence");
59406
+ const normalizedPath = path51.resolve(filePath);
59241
59407
  return normalizedPath.startsWith(swarmPath);
59242
59408
  }
59243
59409
  function readEvidenceFile(evidencePath) {
@@ -59318,7 +59484,7 @@ var check_gate_status = createSwarmTool({
59318
59484
  };
59319
59485
  return JSON.stringify(errorResult, null, 2);
59320
59486
  }
59321
- const evidencePath = path50.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
59487
+ const evidencePath = path51.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
59322
59488
  if (!isPathWithinSwarm(evidencePath, directory)) {
59323
59489
  const errorResult = {
59324
59490
  taskId: taskIdInput,
@@ -59412,7 +59578,7 @@ init_co_change_analyzer();
59412
59578
  init_dist();
59413
59579
  init_utils2();
59414
59580
  import * as fs40 from "fs";
59415
- import * as path51 from "path";
59581
+ import * as path52 from "path";
59416
59582
  init_create_tool();
59417
59583
  init_resolve_working_directory();
59418
59584
  function extractMatches(regex, text) {
@@ -59566,10 +59732,10 @@ async function executeCompletionVerify(args2, directory) {
59566
59732
  let hasFileReadFailure = false;
59567
59733
  for (const filePath of fileTargets) {
59568
59734
  const normalizedPath = filePath.replace(/\\/g, "/");
59569
- const resolvedPath = path51.resolve(directory, normalizedPath);
59570
- const projectRoot = path51.resolve(directory);
59571
- const relative9 = path51.relative(projectRoot, resolvedPath);
59572
- const withinProject = relative9 === "" || !relative9.startsWith("..") && !path51.isAbsolute(relative9);
59735
+ const resolvedPath = path52.resolve(directory, normalizedPath);
59736
+ const projectRoot = path52.resolve(directory);
59737
+ const relative9 = path52.relative(projectRoot, resolvedPath);
59738
+ const withinProject = relative9 === "" || !relative9.startsWith("..") && !path52.isAbsolute(relative9);
59573
59739
  if (!withinProject) {
59574
59740
  blockedTasks.push({
59575
59741
  task_id: task.id,
@@ -59624,8 +59790,8 @@ async function executeCompletionVerify(args2, directory) {
59624
59790
  blockedTasks
59625
59791
  };
59626
59792
  try {
59627
- const evidenceDir = path51.join(directory, ".swarm", "evidence", `${phase}`);
59628
- const evidencePath = path51.join(evidenceDir, "completion-verify.json");
59793
+ const evidenceDir = path52.join(directory, ".swarm", "evidence", `${phase}`);
59794
+ const evidencePath = path52.join(evidenceDir, "completion-verify.json");
59629
59795
  fs40.mkdirSync(evidenceDir, { recursive: true });
59630
59796
  const evidenceBundle = {
59631
59797
  schema_version: "1.0.0",
@@ -59702,11 +59868,11 @@ var completion_verify = createSwarmTool({
59702
59868
  // src/tools/complexity-hotspots.ts
59703
59869
  init_dist();
59704
59870
  import * as fs42 from "fs";
59705
- import * as path53 from "path";
59871
+ import * as path54 from "path";
59706
59872
 
59707
59873
  // src/quality/metrics.ts
59708
59874
  import * as fs41 from "fs";
59709
- import * as path52 from "path";
59875
+ import * as path53 from "path";
59710
59876
  var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
59711
59877
  var MIN_DUPLICATION_LINES = 10;
59712
59878
  function estimateCyclomaticComplexity(content) {
@@ -59758,7 +59924,7 @@ async function computeComplexityDelta(files, workingDir) {
59758
59924
  let totalComplexity = 0;
59759
59925
  const analyzedFiles = [];
59760
59926
  for (const file3 of files) {
59761
- const fullPath = path52.isAbsolute(file3) ? file3 : path52.join(workingDir, file3);
59927
+ const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
59762
59928
  if (!fs41.existsSync(fullPath)) {
59763
59929
  continue;
59764
59930
  }
@@ -59881,7 +60047,7 @@ function countGoExports(content) {
59881
60047
  function getExportCountForFile(filePath) {
59882
60048
  try {
59883
60049
  const content = fs41.readFileSync(filePath, "utf-8");
59884
- const ext = path52.extname(filePath).toLowerCase();
60050
+ const ext = path53.extname(filePath).toLowerCase();
59885
60051
  switch (ext) {
59886
60052
  case ".ts":
59887
60053
  case ".tsx":
@@ -59907,7 +60073,7 @@ async function computePublicApiDelta(files, workingDir) {
59907
60073
  let totalExports = 0;
59908
60074
  const analyzedFiles = [];
59909
60075
  for (const file3 of files) {
59910
- const fullPath = path52.isAbsolute(file3) ? file3 : path52.join(workingDir, file3);
60076
+ const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
59911
60077
  if (!fs41.existsSync(fullPath)) {
59912
60078
  continue;
59913
60079
  }
@@ -59941,7 +60107,7 @@ async function computeDuplicationRatio(files, workingDir) {
59941
60107
  let duplicateLines = 0;
59942
60108
  const analyzedFiles = [];
59943
60109
  for (const file3 of files) {
59944
- const fullPath = path52.isAbsolute(file3) ? file3 : path52.join(workingDir, file3);
60110
+ const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
59945
60111
  if (!fs41.existsSync(fullPath)) {
59946
60112
  continue;
59947
60113
  }
@@ -59974,8 +60140,8 @@ function countCodeLines(content) {
59974
60140
  return lines.length;
59975
60141
  }
59976
60142
  function isTestFile(filePath) {
59977
- const basename8 = path52.basename(filePath);
59978
- const _ext = path52.extname(filePath).toLowerCase();
60143
+ const basename8 = path53.basename(filePath);
60144
+ const _ext = path53.extname(filePath).toLowerCase();
59979
60145
  const testPatterns = [
59980
60146
  ".test.",
59981
60147
  ".spec.",
@@ -60056,8 +60222,8 @@ function matchGlobSegment(globSegments, pathSegments) {
60056
60222
  }
60057
60223
  return gIndex === globSegments.length && pIndex === pathSegments.length;
60058
60224
  }
60059
- function matchesGlobSegment(path53, glob) {
60060
- const normalizedPath = path53.replace(/\\/g, "/");
60225
+ function matchesGlobSegment(path54, glob) {
60226
+ const normalizedPath = path54.replace(/\\/g, "/");
60061
60227
  const normalizedGlob = glob.replace(/\\/g, "/");
60062
60228
  if (normalizedPath.includes("//")) {
60063
60229
  return false;
@@ -60088,8 +60254,8 @@ function simpleGlobToRegex2(glob) {
60088
60254
  function hasGlobstar(glob) {
60089
60255
  return glob.includes("**");
60090
60256
  }
60091
- function globMatches(path53, glob) {
60092
- const normalizedPath = path53.replace(/\\/g, "/");
60257
+ function globMatches(path54, glob) {
60258
+ const normalizedPath = path54.replace(/\\/g, "/");
60093
60259
  if (!glob || glob === "") {
60094
60260
  if (normalizedPath.includes("//")) {
60095
60261
  return false;
@@ -60125,7 +60291,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
60125
60291
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
60126
60292
  let testLines = 0;
60127
60293
  let codeLines = 0;
60128
- const srcDir = path52.join(workingDir, "src");
60294
+ const srcDir = path53.join(workingDir, "src");
60129
60295
  if (fs41.existsSync(srcDir)) {
60130
60296
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
60131
60297
  codeLines += lines;
@@ -60133,14 +60299,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
60133
60299
  }
60134
60300
  const possibleSrcDirs = ["lib", "app", "source", "core"];
60135
60301
  for (const dir of possibleSrcDirs) {
60136
- const dirPath = path52.join(workingDir, dir);
60302
+ const dirPath = path53.join(workingDir, dir);
60137
60303
  if (fs41.existsSync(dirPath)) {
60138
60304
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
60139
60305
  codeLines += lines;
60140
60306
  });
60141
60307
  }
60142
60308
  }
60143
- const testsDir = path52.join(workingDir, "tests");
60309
+ const testsDir = path53.join(workingDir, "tests");
60144
60310
  if (fs41.existsSync(testsDir)) {
60145
60311
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
60146
60312
  testLines += lines;
@@ -60148,7 +60314,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
60148
60314
  }
60149
60315
  const possibleTestDirs = ["test", "__tests__", "specs"];
60150
60316
  for (const dir of possibleTestDirs) {
60151
- const dirPath = path52.join(workingDir, dir);
60317
+ const dirPath = path53.join(workingDir, dir);
60152
60318
  if (fs41.existsSync(dirPath) && dirPath !== testsDir) {
60153
60319
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
60154
60320
  testLines += lines;
@@ -60163,7 +60329,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
60163
60329
  try {
60164
60330
  const entries = fs41.readdirSync(dirPath, { withFileTypes: true });
60165
60331
  for (const entry of entries) {
60166
- const fullPath = path52.join(dirPath, entry.name);
60332
+ const fullPath = path53.join(dirPath, entry.name);
60167
60333
  if (entry.isDirectory()) {
60168
60334
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
60169
60335
  continue;
@@ -60171,7 +60337,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
60171
60337
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
60172
60338
  } else if (entry.isFile()) {
60173
60339
  const relativePath = fullPath.replace(`${dirPath}/`, "");
60174
- const ext = path52.extname(entry.name).toLowerCase();
60340
+ const ext = path53.extname(entry.name).toLowerCase();
60175
60341
  const validExts = [
60176
60342
  ".ts",
60177
60343
  ".tsx",
@@ -60423,7 +60589,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
60423
60589
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
60424
60590
  const filteredChurn = new Map;
60425
60591
  for (const [file3, count] of churnMap) {
60426
- const ext = path53.extname(file3).toLowerCase();
60592
+ const ext = path54.extname(file3).toLowerCase();
60427
60593
  if (extSet.has(ext)) {
60428
60594
  filteredChurn.set(file3, count);
60429
60595
  }
@@ -60434,7 +60600,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
60434
60600
  for (const [file3, churnCount] of filteredChurn) {
60435
60601
  let fullPath = file3;
60436
60602
  if (!fs42.existsSync(fullPath)) {
60437
- fullPath = path53.join(cwd, file3);
60603
+ fullPath = path54.join(cwd, file3);
60438
60604
  }
60439
60605
  const complexity = getComplexityForFile2(fullPath);
60440
60606
  if (complexity !== null) {
@@ -60682,7 +60848,7 @@ var curator_analyze = createSwarmTool({
60682
60848
  // src/tools/declare-scope.ts
60683
60849
  init_tool();
60684
60850
  import * as fs43 from "fs";
60685
- import * as path54 from "path";
60851
+ import * as path55 from "path";
60686
60852
  init_create_tool();
60687
60853
  function validateTaskIdFormat(taskId) {
60688
60854
  const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
@@ -60761,8 +60927,8 @@ async function executeDeclareScope(args2, fallbackDir) {
60761
60927
  };
60762
60928
  }
60763
60929
  }
60764
- normalizedDir = path54.normalize(args2.working_directory);
60765
- const pathParts = normalizedDir.split(path54.sep);
60930
+ normalizedDir = path55.normalize(args2.working_directory);
60931
+ const pathParts = normalizedDir.split(path55.sep);
60766
60932
  if (pathParts.includes("..")) {
60767
60933
  return {
60768
60934
  success: false,
@@ -60772,10 +60938,10 @@ async function executeDeclareScope(args2, fallbackDir) {
60772
60938
  ]
60773
60939
  };
60774
60940
  }
60775
- const resolvedDir = path54.resolve(normalizedDir);
60941
+ const resolvedDir = path55.resolve(normalizedDir);
60776
60942
  try {
60777
60943
  const realPath = fs43.realpathSync(resolvedDir);
60778
- const planPath2 = path54.join(realPath, ".swarm", "plan.json");
60944
+ const planPath2 = path55.join(realPath, ".swarm", "plan.json");
60779
60945
  if (!fs43.existsSync(planPath2)) {
60780
60946
  return {
60781
60947
  success: false,
@@ -60799,7 +60965,7 @@ async function executeDeclareScope(args2, fallbackDir) {
60799
60965
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
60800
60966
  }
60801
60967
  const directory = normalizedDir || fallbackDir;
60802
- const planPath = path54.resolve(directory, ".swarm", "plan.json");
60968
+ const planPath = path55.resolve(directory, ".swarm", "plan.json");
60803
60969
  if (!fs43.existsSync(planPath)) {
60804
60970
  return {
60805
60971
  success: false,
@@ -60841,8 +61007,8 @@ async function executeDeclareScope(args2, fallbackDir) {
60841
61007
  const normalizeErrors = [];
60842
61008
  const dir = normalizedDir || fallbackDir || process.cwd();
60843
61009
  const mergedFiles = rawMergedFiles.map((file3) => {
60844
- if (path54.isAbsolute(file3)) {
60845
- const relativePath = path54.relative(dir, file3).replace(/\\/g, "/");
61010
+ if (path55.isAbsolute(file3)) {
61011
+ const relativePath = path55.relative(dir, file3).replace(/\\/g, "/");
60846
61012
  if (relativePath.startsWith("..")) {
60847
61013
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
60848
61014
  return file3;
@@ -61168,20 +61334,20 @@ function validateBase(base) {
61168
61334
  function validatePaths(paths) {
61169
61335
  if (!paths)
61170
61336
  return null;
61171
- for (const path56 of paths) {
61172
- if (!path56 || path56.length === 0) {
61337
+ for (const path57 of paths) {
61338
+ if (!path57 || path57.length === 0) {
61173
61339
  return "empty path not allowed";
61174
61340
  }
61175
- if (path56.length > MAX_PATH_LENGTH) {
61341
+ if (path57.length > MAX_PATH_LENGTH) {
61176
61342
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
61177
61343
  }
61178
- if (SHELL_METACHARACTERS2.test(path56)) {
61344
+ if (SHELL_METACHARACTERS2.test(path57)) {
61179
61345
  return "path contains shell metacharacters";
61180
61346
  }
61181
- if (path56.startsWith("-")) {
61347
+ if (path57.startsWith("-")) {
61182
61348
  return 'path cannot start with "-" (option-like arguments not allowed)';
61183
61349
  }
61184
- if (CONTROL_CHAR_PATTERN2.test(path56)) {
61350
+ if (CONTROL_CHAR_PATTERN2.test(path57)) {
61185
61351
  return "path contains control characters";
61186
61352
  }
61187
61353
  }
@@ -61262,8 +61428,8 @@ var diff = createSwarmTool({
61262
61428
  if (parts2.length >= 3) {
61263
61429
  const additions = parseInt(parts2[0], 10) || 0;
61264
61430
  const deletions = parseInt(parts2[1], 10) || 0;
61265
- const path56 = parts2[2];
61266
- files.push({ path: path56, additions, deletions });
61431
+ const path57 = parts2[2];
61432
+ files.push({ path: path57, additions, deletions });
61267
61433
  }
61268
61434
  }
61269
61435
  const contractChanges = [];
@@ -61546,7 +61712,7 @@ Use these as DOMAIN values when delegating to @sme.`;
61546
61712
  init_dist();
61547
61713
  init_create_tool();
61548
61714
  import * as fs44 from "fs";
61549
- import * as path56 from "path";
61715
+ import * as path57 from "path";
61550
61716
  var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
61551
61717
  var MAX_EVIDENCE_FILES = 1000;
61552
61718
  var EVIDENCE_DIR2 = ".swarm/evidence";
@@ -61573,9 +61739,9 @@ function validateRequiredTypes(input) {
61573
61739
  return null;
61574
61740
  }
61575
61741
  function isPathWithinSwarm2(filePath, cwd) {
61576
- const normalizedCwd = path56.resolve(cwd);
61577
- const swarmPath = path56.join(normalizedCwd, ".swarm");
61578
- const normalizedPath = path56.resolve(filePath);
61742
+ const normalizedCwd = path57.resolve(cwd);
61743
+ const swarmPath = path57.join(normalizedCwd, ".swarm");
61744
+ const normalizedPath = path57.resolve(filePath);
61579
61745
  return normalizedPath.startsWith(swarmPath);
61580
61746
  }
61581
61747
  function parseCompletedTasks(planContent) {
@@ -61605,10 +61771,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
61605
61771
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
61606
61772
  continue;
61607
61773
  }
61608
- const filePath = path56.join(evidenceDir, filename);
61774
+ const filePath = path57.join(evidenceDir, filename);
61609
61775
  try {
61610
- const resolvedPath = path56.resolve(filePath);
61611
- const evidenceDirResolved = path56.resolve(evidenceDir);
61776
+ const resolvedPath = path57.resolve(filePath);
61777
+ const evidenceDirResolved = path57.resolve(evidenceDir);
61612
61778
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
61613
61779
  continue;
61614
61780
  }
@@ -61726,7 +61892,7 @@ var evidence_check = createSwarmTool({
61726
61892
  return JSON.stringify(errorResult, null, 2);
61727
61893
  }
61728
61894
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
61729
- const planPath = path56.join(cwd, PLAN_FILE);
61895
+ const planPath = path57.join(cwd, PLAN_FILE);
61730
61896
  if (!isPathWithinSwarm2(planPath, cwd)) {
61731
61897
  const errorResult = {
61732
61898
  error: "plan file path validation failed",
@@ -61758,7 +61924,7 @@ var evidence_check = createSwarmTool({
61758
61924
  };
61759
61925
  return JSON.stringify(result2, null, 2);
61760
61926
  }
61761
- const evidenceDir = path56.join(cwd, EVIDENCE_DIR2);
61927
+ const evidenceDir = path57.join(cwd, EVIDENCE_DIR2);
61762
61928
  const evidence = readEvidenceFiles(evidenceDir, cwd);
61763
61929
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
61764
61930
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -61776,7 +61942,7 @@ var evidence_check = createSwarmTool({
61776
61942
  init_tool();
61777
61943
  init_create_tool();
61778
61944
  import * as fs45 from "fs";
61779
- import * as path57 from "path";
61945
+ import * as path58 from "path";
61780
61946
  var EXT_MAP = {
61781
61947
  python: ".py",
61782
61948
  py: ".py",
@@ -61857,12 +62023,12 @@ var extract_code_blocks = createSwarmTool({
61857
62023
  if (prefix) {
61858
62024
  filename = `${prefix}_${filename}`;
61859
62025
  }
61860
- let filepath = path57.join(targetDir, filename);
61861
- const base = path57.basename(filepath, path57.extname(filepath));
61862
- const ext = path57.extname(filepath);
62026
+ let filepath = path58.join(targetDir, filename);
62027
+ const base = path58.basename(filepath, path58.extname(filepath));
62028
+ const ext = path58.extname(filepath);
61863
62029
  let counter = 1;
61864
62030
  while (fs45.existsSync(filepath)) {
61865
- filepath = path57.join(targetDir, `${base}_${counter}${ext}`);
62031
+ filepath = path58.join(targetDir, `${base}_${counter}${ext}`);
61866
62032
  counter++;
61867
62033
  }
61868
62034
  try {
@@ -61983,7 +62149,7 @@ var gitingest = createSwarmTool({
61983
62149
  init_dist();
61984
62150
  init_create_tool();
61985
62151
  import * as fs46 from "fs";
61986
- import * as path58 from "path";
62152
+ import * as path59 from "path";
61987
62153
  var MAX_FILE_PATH_LENGTH2 = 500;
61988
62154
  var MAX_SYMBOL_LENGTH = 256;
61989
62155
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
@@ -62031,7 +62197,7 @@ function validateSymbolInput(symbol3) {
62031
62197
  return null;
62032
62198
  }
62033
62199
  function isBinaryFile2(filePath, buffer) {
62034
- const ext = path58.extname(filePath).toLowerCase();
62200
+ const ext = path59.extname(filePath).toLowerCase();
62035
62201
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
62036
62202
  return false;
62037
62203
  }
@@ -62055,15 +62221,15 @@ function parseImports(content, targetFile, targetSymbol) {
62055
62221
  const imports = [];
62056
62222
  let _resolvedTarget;
62057
62223
  try {
62058
- _resolvedTarget = path58.resolve(targetFile);
62224
+ _resolvedTarget = path59.resolve(targetFile);
62059
62225
  } catch {
62060
62226
  _resolvedTarget = targetFile;
62061
62227
  }
62062
- const targetBasename = path58.basename(targetFile, path58.extname(targetFile));
62228
+ const targetBasename = path59.basename(targetFile, path59.extname(targetFile));
62063
62229
  const targetWithExt = targetFile;
62064
62230
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
62065
- const normalizedTargetWithExt = path58.normalize(targetWithExt).replace(/\\/g, "/");
62066
- const normalizedTargetWithoutExt = path58.normalize(targetWithoutExt).replace(/\\/g, "/");
62231
+ const normalizedTargetWithExt = path59.normalize(targetWithExt).replace(/\\/g, "/");
62232
+ const normalizedTargetWithoutExt = path59.normalize(targetWithoutExt).replace(/\\/g, "/");
62067
62233
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
62068
62234
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
62069
62235
  const modulePath = match[1] || match[2] || match[3];
@@ -62086,9 +62252,9 @@ function parseImports(content, targetFile, targetSymbol) {
62086
62252
  }
62087
62253
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
62088
62254
  let isMatch = false;
62089
- const _targetDir = path58.dirname(targetFile);
62090
- const targetExt = path58.extname(targetFile);
62091
- const targetBasenameNoExt = path58.basename(targetFile, targetExt);
62255
+ const _targetDir = path59.dirname(targetFile);
62256
+ const targetExt = path59.extname(targetFile);
62257
+ const targetBasenameNoExt = path59.basename(targetFile, targetExt);
62092
62258
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
62093
62259
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
62094
62260
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -62156,10 +62322,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
62156
62322
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
62157
62323
  for (const entry of entries) {
62158
62324
  if (SKIP_DIRECTORIES3.has(entry)) {
62159
- stats.skippedDirs.push(path58.join(dir, entry));
62325
+ stats.skippedDirs.push(path59.join(dir, entry));
62160
62326
  continue;
62161
62327
  }
62162
- const fullPath = path58.join(dir, entry);
62328
+ const fullPath = path59.join(dir, entry);
62163
62329
  let stat2;
62164
62330
  try {
62165
62331
  stat2 = fs46.statSync(fullPath);
@@ -62173,7 +62339,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
62173
62339
  if (stat2.isDirectory()) {
62174
62340
  findSourceFiles(fullPath, files, stats);
62175
62341
  } else if (stat2.isFile()) {
62176
- const ext = path58.extname(fullPath).toLowerCase();
62342
+ const ext = path59.extname(fullPath).toLowerCase();
62177
62343
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
62178
62344
  files.push(fullPath);
62179
62345
  }
@@ -62230,7 +62396,7 @@ var imports = createSwarmTool({
62230
62396
  return JSON.stringify(errorResult, null, 2);
62231
62397
  }
62232
62398
  try {
62233
- const targetFile = path58.resolve(file3);
62399
+ const targetFile = path59.resolve(file3);
62234
62400
  if (!fs46.existsSync(targetFile)) {
62235
62401
  const errorResult = {
62236
62402
  error: `target file not found: ${file3}`,
@@ -62252,7 +62418,7 @@ var imports = createSwarmTool({
62252
62418
  };
62253
62419
  return JSON.stringify(errorResult, null, 2);
62254
62420
  }
62255
- const baseDir = path58.dirname(targetFile);
62421
+ const baseDir = path59.dirname(targetFile);
62256
62422
  const scanStats = {
62257
62423
  skippedDirs: [],
62258
62424
  skippedFiles: 0,
@@ -62472,7 +62638,7 @@ init_dist();
62472
62638
  init_config();
62473
62639
  init_knowledge_store();
62474
62640
  init_create_tool();
62475
- import { existsSync as existsSync36 } from "fs";
62641
+ import { existsSync as existsSync37 } from "fs";
62476
62642
  var DEFAULT_LIMIT = 10;
62477
62643
  var MAX_LESSON_LENGTH = 200;
62478
62644
  var VALID_CATEGORIES3 = [
@@ -62541,14 +62707,14 @@ function validateLimit(limit) {
62541
62707
  }
62542
62708
  async function readSwarmKnowledge(directory) {
62543
62709
  const swarmPath = resolveSwarmKnowledgePath(directory);
62544
- if (!existsSync36(swarmPath)) {
62710
+ if (!existsSync37(swarmPath)) {
62545
62711
  return [];
62546
62712
  }
62547
62713
  return readKnowledge(swarmPath);
62548
62714
  }
62549
62715
  async function readHiveKnowledge() {
62550
62716
  const hivePath = resolveHiveKnowledgePath();
62551
- if (!existsSync36(hivePath)) {
62717
+ if (!existsSync37(hivePath)) {
62552
62718
  return [];
62553
62719
  }
62554
62720
  return readKnowledge(hivePath);
@@ -62862,7 +63028,7 @@ init_config();
62862
63028
  init_schema();
62863
63029
  init_manager();
62864
63030
  import * as fs47 from "fs";
62865
- import * as path59 from "path";
63031
+ import * as path60 from "path";
62866
63032
  init_review_receipt();
62867
63033
  init_utils2();
62868
63034
  init_ledger();
@@ -63086,7 +63252,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
63086
63252
  safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
63087
63253
  }
63088
63254
  try {
63089
- const driftEvidencePath = path59.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
63255
+ const driftEvidencePath = path60.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
63090
63256
  let driftVerdictFound = false;
63091
63257
  let driftVerdictApproved = false;
63092
63258
  try {
@@ -63120,7 +63286,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
63120
63286
  driftVerdictFound = false;
63121
63287
  }
63122
63288
  if (!driftVerdictFound) {
63123
- const specPath = path59.join(dir, ".swarm", "spec.md");
63289
+ const specPath = path60.join(dir, ".swarm", "spec.md");
63124
63290
  const specExists = fs47.existsSync(specPath);
63125
63291
  if (!specExists) {
63126
63292
  let incompleteTaskCount = 0;
@@ -63172,7 +63338,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
63172
63338
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
63173
63339
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
63174
63340
  try {
63175
- const projectName = path59.basename(dir);
63341
+ const projectName = path60.basename(dir);
63176
63342
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
63177
63343
  if (curationResult) {
63178
63344
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -63492,7 +63658,7 @@ init_discovery();
63492
63658
  init_utils();
63493
63659
  init_create_tool();
63494
63660
  import * as fs48 from "fs";
63495
- import * as path60 from "path";
63661
+ import * as path61 from "path";
63496
63662
  var MAX_OUTPUT_BYTES5 = 52428800;
63497
63663
  var AUDIT_TIMEOUT_MS = 120000;
63498
63664
  function isValidEcosystem(value) {
@@ -63510,16 +63676,16 @@ function validateArgs3(args2) {
63510
63676
  function detectEcosystems(directory) {
63511
63677
  const ecosystems = [];
63512
63678
  const cwd = directory;
63513
- if (fs48.existsSync(path60.join(cwd, "package.json"))) {
63679
+ if (fs48.existsSync(path61.join(cwd, "package.json"))) {
63514
63680
  ecosystems.push("npm");
63515
63681
  }
63516
- if (fs48.existsSync(path60.join(cwd, "pyproject.toml")) || fs48.existsSync(path60.join(cwd, "requirements.txt"))) {
63682
+ if (fs48.existsSync(path61.join(cwd, "pyproject.toml")) || fs48.existsSync(path61.join(cwd, "requirements.txt"))) {
63517
63683
  ecosystems.push("pip");
63518
63684
  }
63519
- if (fs48.existsSync(path60.join(cwd, "Cargo.toml"))) {
63685
+ if (fs48.existsSync(path61.join(cwd, "Cargo.toml"))) {
63520
63686
  ecosystems.push("cargo");
63521
63687
  }
63522
- if (fs48.existsSync(path60.join(cwd, "go.mod"))) {
63688
+ if (fs48.existsSync(path61.join(cwd, "go.mod"))) {
63523
63689
  ecosystems.push("go");
63524
63690
  }
63525
63691
  try {
@@ -63528,10 +63694,10 @@ function detectEcosystems(directory) {
63528
63694
  ecosystems.push("dotnet");
63529
63695
  }
63530
63696
  } catch {}
63531
- if (fs48.existsSync(path60.join(cwd, "Gemfile")) || fs48.existsSync(path60.join(cwd, "Gemfile.lock"))) {
63697
+ if (fs48.existsSync(path61.join(cwd, "Gemfile")) || fs48.existsSync(path61.join(cwd, "Gemfile.lock"))) {
63532
63698
  ecosystems.push("ruby");
63533
63699
  }
63534
- if (fs48.existsSync(path60.join(cwd, "pubspec.yaml"))) {
63700
+ if (fs48.existsSync(path61.join(cwd, "pubspec.yaml"))) {
63535
63701
  ecosystems.push("dart");
63536
63702
  }
63537
63703
  return ecosystems;
@@ -64554,7 +64720,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
64554
64720
  // src/tools/pre-check-batch.ts
64555
64721
  init_dist();
64556
64722
  import * as fs50 from "fs";
64557
- import * as path62 from "path";
64723
+ import * as path63 from "path";
64558
64724
 
64559
64725
  // node_modules/yocto-queue/index.js
64560
64726
  class Node2 {
@@ -64829,7 +64995,7 @@ init_dist();
64829
64995
  init_manager();
64830
64996
  init_detector();
64831
64997
  import * as fs49 from "fs";
64832
- import * as path61 from "path";
64998
+ import * as path62 from "path";
64833
64999
  import { extname as extname12 } from "path";
64834
65000
 
64835
65001
  // src/sast/rules/c.ts
@@ -65795,9 +65961,9 @@ async function sastScan(input, directory, config3) {
65795
65961
  _filesSkipped++;
65796
65962
  continue;
65797
65963
  }
65798
- const resolvedPath = path61.isAbsolute(filePath) ? filePath : path61.resolve(directory, filePath);
65799
- const resolvedDirectory = path61.resolve(directory);
65800
- if (!resolvedPath.startsWith(resolvedDirectory + path61.sep) && resolvedPath !== resolvedDirectory) {
65964
+ const resolvedPath = path62.isAbsolute(filePath) ? filePath : path62.resolve(directory, filePath);
65965
+ const resolvedDirectory = path62.resolve(directory);
65966
+ if (!resolvedPath.startsWith(resolvedDirectory + path62.sep) && resolvedPath !== resolvedDirectory) {
65801
65967
  _filesSkipped++;
65802
65968
  continue;
65803
65969
  }
@@ -65999,18 +66165,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
65999
66165
  let resolved;
66000
66166
  const isWinAbs = isWindowsAbsolutePath(inputPath);
66001
66167
  if (isWinAbs) {
66002
- resolved = path62.win32.resolve(inputPath);
66003
- } else if (path62.isAbsolute(inputPath)) {
66004
- resolved = path62.resolve(inputPath);
66168
+ resolved = path63.win32.resolve(inputPath);
66169
+ } else if (path63.isAbsolute(inputPath)) {
66170
+ resolved = path63.resolve(inputPath);
66005
66171
  } else {
66006
- resolved = path62.resolve(baseDir, inputPath);
66172
+ resolved = path63.resolve(baseDir, inputPath);
66007
66173
  }
66008
- const workspaceResolved = path62.resolve(workspaceDir);
66174
+ const workspaceResolved = path63.resolve(workspaceDir);
66009
66175
  let relative11;
66010
66176
  if (isWinAbs) {
66011
- relative11 = path62.win32.relative(workspaceResolved, resolved);
66177
+ relative11 = path63.win32.relative(workspaceResolved, resolved);
66012
66178
  } else {
66013
- relative11 = path62.relative(workspaceResolved, resolved);
66179
+ relative11 = path63.relative(workspaceResolved, resolved);
66014
66180
  }
66015
66181
  if (relative11.startsWith("..")) {
66016
66182
  return "path traversal detected";
@@ -66075,7 +66241,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
66075
66241
  if (typeof file3 !== "string") {
66076
66242
  continue;
66077
66243
  }
66078
- const resolvedPath = path62.resolve(file3);
66244
+ const resolvedPath = path63.resolve(file3);
66079
66245
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
66080
66246
  if (validationError) {
66081
66247
  continue;
@@ -66232,7 +66398,7 @@ async function runSecretscanWithFiles(files, directory) {
66232
66398
  skippedFiles++;
66233
66399
  continue;
66234
66400
  }
66235
- const resolvedPath = path62.resolve(file3);
66401
+ const resolvedPath = path63.resolve(file3);
66236
66402
  const validationError = validatePath(resolvedPath, directory, directory);
66237
66403
  if (validationError) {
66238
66404
  skippedFiles++;
@@ -66250,7 +66416,7 @@ async function runSecretscanWithFiles(files, directory) {
66250
66416
  };
66251
66417
  }
66252
66418
  for (const file3 of validatedFiles) {
66253
- const ext = path62.extname(file3).toLowerCase();
66419
+ const ext = path63.extname(file3).toLowerCase();
66254
66420
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
66255
66421
  skippedFiles++;
66256
66422
  continue;
@@ -66456,7 +66622,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
66456
66622
  const preexistingFindings = [];
66457
66623
  for (const finding of findings) {
66458
66624
  const filePath = finding.location.file;
66459
- const normalised = path62.relative(directory, filePath).replace(/\\/g, "/");
66625
+ const normalised = path63.relative(directory, filePath).replace(/\\/g, "/");
66460
66626
  const changedLines = changedLineRanges.get(normalised);
66461
66627
  if (changedLines && changedLines.has(finding.location.line)) {
66462
66628
  newFindings.push(finding);
@@ -66507,7 +66673,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
66507
66673
  warn(`pre_check_batch: Invalid file path: ${file3}`);
66508
66674
  continue;
66509
66675
  }
66510
- changedFiles.push(path62.resolve(directory, file3));
66676
+ changedFiles.push(path63.resolve(directory, file3));
66511
66677
  }
66512
66678
  if (changedFiles.length === 0) {
66513
66679
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -66695,7 +66861,7 @@ var pre_check_batch = createSwarmTool({
66695
66861
  };
66696
66862
  return JSON.stringify(errorResult, null, 2);
66697
66863
  }
66698
- const resolvedDirectory = path62.resolve(typedArgs.directory);
66864
+ const resolvedDirectory = path63.resolve(typedArgs.directory);
66699
66865
  const workspaceAnchor = resolvedDirectory;
66700
66866
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
66701
66867
  if (dirError) {
@@ -66802,25 +66968,25 @@ ${paginatedContent}`;
66802
66968
  // src/tools/save-plan.ts
66803
66969
  init_tool();
66804
66970
  import * as fs52 from "fs";
66805
- import * as path64 from "path";
66971
+ import * as path65 from "path";
66806
66972
 
66807
66973
  // src/parallel/file-locks.ts
66808
66974
  var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
66809
66975
  import * as fs51 from "fs";
66810
- import * as path63 from "path";
66976
+ import * as path64 from "path";
66811
66977
  var LOCKS_DIR = ".swarm/locks";
66812
66978
  var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
66813
66979
  function getLockFilePath(directory, filePath) {
66814
- const normalized = path63.resolve(directory, filePath);
66815
- if (!normalized.startsWith(path63.resolve(directory))) {
66980
+ const normalized = path64.resolve(directory, filePath);
66981
+ if (!normalized.startsWith(path64.resolve(directory))) {
66816
66982
  throw new Error("Invalid file path: path traversal not allowed");
66817
66983
  }
66818
66984
  const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
66819
- return path63.join(directory, LOCKS_DIR, `${hash3}.lock`);
66985
+ return path64.join(directory, LOCKS_DIR, `${hash3}.lock`);
66820
66986
  }
66821
66987
  async function tryAcquireLock(directory, filePath, agent, taskId) {
66822
66988
  const lockPath = getLockFilePath(directory, filePath);
66823
- const locksDir = path63.dirname(lockPath);
66989
+ const locksDir = path64.dirname(lockPath);
66824
66990
  if (!fs51.existsSync(locksDir)) {
66825
66991
  fs51.mkdirSync(locksDir, { recursive: true });
66826
66992
  }
@@ -66973,7 +67139,7 @@ async function executeSavePlan(args2, fallbackDir) {
66973
67139
  await savePlan(dir, plan);
66974
67140
  await writeCheckpoint(dir).catch(() => {});
66975
67141
  try {
66976
- const markerPath = path64.join(dir, ".swarm", ".plan-write-marker");
67142
+ const markerPath = path65.join(dir, ".swarm", ".plan-write-marker");
66977
67143
  const marker = JSON.stringify({
66978
67144
  source: "save_plan",
66979
67145
  timestamp: new Date().toISOString(),
@@ -66996,7 +67162,7 @@ async function executeSavePlan(args2, fallbackDir) {
66996
67162
  return {
66997
67163
  success: true,
66998
67164
  message: "Plan saved successfully",
66999
- plan_path: path64.join(dir, ".swarm", "plan.json"),
67165
+ plan_path: path65.join(dir, ".swarm", "plan.json"),
67000
67166
  phases_count: plan.phases.length,
67001
67167
  tasks_count: tasksCount,
67002
67168
  ...warnings.length > 0 ? { warnings } : {}
@@ -67041,7 +67207,7 @@ var save_plan = createSwarmTool({
67041
67207
  init_dist();
67042
67208
  init_manager();
67043
67209
  import * as fs53 from "fs";
67044
- import * as path65 from "path";
67210
+ import * as path66 from "path";
67045
67211
 
67046
67212
  // src/sbom/detectors/index.ts
67047
67213
  init_utils();
@@ -67891,7 +68057,7 @@ function findManifestFiles(rootDir) {
67891
68057
  try {
67892
68058
  const entries = fs53.readdirSync(dir, { withFileTypes: true });
67893
68059
  for (const entry of entries) {
67894
- const fullPath = path65.join(dir, entry.name);
68060
+ const fullPath = path66.join(dir, entry.name);
67895
68061
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
67896
68062
  continue;
67897
68063
  }
@@ -67900,7 +68066,7 @@ function findManifestFiles(rootDir) {
67900
68066
  } else if (entry.isFile()) {
67901
68067
  for (const pattern of patterns) {
67902
68068
  if (simpleGlobToRegex(pattern).test(entry.name)) {
67903
- manifestFiles.push(path65.relative(rootDir, fullPath));
68069
+ manifestFiles.push(path66.relative(rootDir, fullPath));
67904
68070
  break;
67905
68071
  }
67906
68072
  }
@@ -67918,11 +68084,11 @@ function findManifestFilesInDirs(directories, workingDir) {
67918
68084
  try {
67919
68085
  const entries = fs53.readdirSync(dir, { withFileTypes: true });
67920
68086
  for (const entry of entries) {
67921
- const fullPath = path65.join(dir, entry.name);
68087
+ const fullPath = path66.join(dir, entry.name);
67922
68088
  if (entry.isFile()) {
67923
68089
  for (const pattern of patterns) {
67924
68090
  if (simpleGlobToRegex(pattern).test(entry.name)) {
67925
- found.push(path65.relative(workingDir, fullPath));
68091
+ found.push(path66.relative(workingDir, fullPath));
67926
68092
  break;
67927
68093
  }
67928
68094
  }
@@ -67935,11 +68101,11 @@ function findManifestFilesInDirs(directories, workingDir) {
67935
68101
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
67936
68102
  const dirs = new Set;
67937
68103
  for (const file3 of changedFiles) {
67938
- let currentDir = path65.dirname(file3);
68104
+ let currentDir = path66.dirname(file3);
67939
68105
  while (true) {
67940
- if (currentDir && currentDir !== "." && currentDir !== path65.sep) {
67941
- dirs.add(path65.join(workingDir, currentDir));
67942
- const parent = path65.dirname(currentDir);
68106
+ if (currentDir && currentDir !== "." && currentDir !== path66.sep) {
68107
+ dirs.add(path66.join(workingDir, currentDir));
68108
+ const parent = path66.dirname(currentDir);
67943
68109
  if (parent === currentDir)
67944
68110
  break;
67945
68111
  currentDir = parent;
@@ -68023,7 +68189,7 @@ var sbom_generate = createSwarmTool({
68023
68189
  const changedFiles = obj.changed_files;
68024
68190
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
68025
68191
  const workingDir = directory;
68026
- const outputDir = path65.isAbsolute(relativeOutputDir) ? relativeOutputDir : path65.join(workingDir, relativeOutputDir);
68192
+ const outputDir = path66.isAbsolute(relativeOutputDir) ? relativeOutputDir : path66.join(workingDir, relativeOutputDir);
68027
68193
  let manifestFiles = [];
68028
68194
  if (scope === "all") {
68029
68195
  manifestFiles = findManifestFiles(workingDir);
@@ -68046,7 +68212,7 @@ var sbom_generate = createSwarmTool({
68046
68212
  const processedFiles = [];
68047
68213
  for (const manifestFile of manifestFiles) {
68048
68214
  try {
68049
- const fullPath = path65.isAbsolute(manifestFile) ? manifestFile : path65.join(workingDir, manifestFile);
68215
+ const fullPath = path66.isAbsolute(manifestFile) ? manifestFile : path66.join(workingDir, manifestFile);
68050
68216
  if (!fs53.existsSync(fullPath)) {
68051
68217
  continue;
68052
68218
  }
@@ -68063,7 +68229,7 @@ var sbom_generate = createSwarmTool({
68063
68229
  const bom = generateCycloneDX(allComponents);
68064
68230
  const bomJson = serializeCycloneDX(bom);
68065
68231
  const filename = generateSbomFilename();
68066
- const outputPath = path65.join(outputDir, filename);
68232
+ const outputPath = path66.join(outputDir, filename);
68067
68233
  fs53.writeFileSync(outputPath, bomJson, "utf-8");
68068
68234
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
68069
68235
  try {
@@ -68107,7 +68273,7 @@ var sbom_generate = createSwarmTool({
68107
68273
  init_dist();
68108
68274
  init_create_tool();
68109
68275
  import * as fs54 from "fs";
68110
- import * as path66 from "path";
68276
+ import * as path67 from "path";
68111
68277
  var SPEC_CANDIDATES = [
68112
68278
  "openapi.json",
68113
68279
  "openapi.yaml",
@@ -68139,12 +68305,12 @@ function normalizePath2(p) {
68139
68305
  }
68140
68306
  function discoverSpecFile(cwd, specFileArg) {
68141
68307
  if (specFileArg) {
68142
- const resolvedPath = path66.resolve(cwd, specFileArg);
68143
- const normalizedCwd = cwd.endsWith(path66.sep) ? cwd : cwd + path66.sep;
68308
+ const resolvedPath = path67.resolve(cwd, specFileArg);
68309
+ const normalizedCwd = cwd.endsWith(path67.sep) ? cwd : cwd + path67.sep;
68144
68310
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
68145
68311
  throw new Error("Invalid spec_file: path traversal detected");
68146
68312
  }
68147
- const ext = path66.extname(resolvedPath).toLowerCase();
68313
+ const ext = path67.extname(resolvedPath).toLowerCase();
68148
68314
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
68149
68315
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
68150
68316
  }
@@ -68158,7 +68324,7 @@ function discoverSpecFile(cwd, specFileArg) {
68158
68324
  return resolvedPath;
68159
68325
  }
68160
68326
  for (const candidate of SPEC_CANDIDATES) {
68161
- const candidatePath = path66.resolve(cwd, candidate);
68327
+ const candidatePath = path67.resolve(cwd, candidate);
68162
68328
  if (fs54.existsSync(candidatePath)) {
68163
68329
  const stats = fs54.statSync(candidatePath);
68164
68330
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -68170,7 +68336,7 @@ function discoverSpecFile(cwd, specFileArg) {
68170
68336
  }
68171
68337
  function parseSpec(specFile) {
68172
68338
  const content = fs54.readFileSync(specFile, "utf-8");
68173
- const ext = path66.extname(specFile).toLowerCase();
68339
+ const ext = path67.extname(specFile).toLowerCase();
68174
68340
  if (ext === ".json") {
68175
68341
  return parseJsonSpec(content);
68176
68342
  }
@@ -68246,7 +68412,7 @@ function extractRoutes(cwd) {
68246
68412
  return;
68247
68413
  }
68248
68414
  for (const entry of entries) {
68249
- const fullPath = path66.join(dir, entry.name);
68415
+ const fullPath = path67.join(dir, entry.name);
68250
68416
  if (entry.isSymbolicLink()) {
68251
68417
  continue;
68252
68418
  }
@@ -68256,7 +68422,7 @@ function extractRoutes(cwd) {
68256
68422
  }
68257
68423
  walkDir(fullPath);
68258
68424
  } else if (entry.isFile()) {
68259
- const ext = path66.extname(entry.name).toLowerCase();
68425
+ const ext = path67.extname(entry.name).toLowerCase();
68260
68426
  const baseName = entry.name.toLowerCase();
68261
68427
  if (![".ts", ".js", ".mjs"].includes(ext)) {
68262
68428
  continue;
@@ -68422,7 +68588,7 @@ var schema_drift = createSwarmTool({
68422
68588
  init_tool();
68423
68589
  init_create_tool();
68424
68590
  import * as fs55 from "fs";
68425
- import * as path67 from "path";
68591
+ import * as path68 from "path";
68426
68592
  var DEFAULT_MAX_RESULTS = 100;
68427
68593
  var DEFAULT_MAX_LINES = 200;
68428
68594
  var REGEX_TIMEOUT_MS = 5000;
@@ -68458,11 +68624,11 @@ function containsWindowsAttacks3(str) {
68458
68624
  }
68459
68625
  function isPathInWorkspace3(filePath, workspace) {
68460
68626
  try {
68461
- const resolvedPath = path67.resolve(workspace, filePath);
68627
+ const resolvedPath = path68.resolve(workspace, filePath);
68462
68628
  const realWorkspace = fs55.realpathSync(workspace);
68463
68629
  const realResolvedPath = fs55.realpathSync(resolvedPath);
68464
- const relativePath = path67.relative(realWorkspace, realResolvedPath);
68465
- if (relativePath.startsWith("..") || path67.isAbsolute(relativePath)) {
68630
+ const relativePath = path68.relative(realWorkspace, realResolvedPath);
68631
+ if (relativePath.startsWith("..") || path68.isAbsolute(relativePath)) {
68466
68632
  return false;
68467
68633
  }
68468
68634
  return true;
@@ -68475,11 +68641,11 @@ function validatePathForRead2(filePath, workspace) {
68475
68641
  }
68476
68642
  function findRgInEnvPath() {
68477
68643
  const searchPath = process.env.PATH ?? "";
68478
- for (const dir of searchPath.split(path67.delimiter)) {
68644
+ for (const dir of searchPath.split(path68.delimiter)) {
68479
68645
  if (!dir)
68480
68646
  continue;
68481
68647
  const isWindows = process.platform === "win32";
68482
- const candidate = path67.join(dir, isWindows ? "rg.exe" : "rg");
68648
+ const candidate = path68.join(dir, isWindows ? "rg.exe" : "rg");
68483
68649
  if (fs55.existsSync(candidate))
68484
68650
  return candidate;
68485
68651
  }
@@ -68609,8 +68775,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
68609
68775
  try {
68610
68776
  const entries = fs55.readdirSync(dir, { withFileTypes: true });
68611
68777
  for (const entry of entries) {
68612
- const fullPath = path67.join(dir, entry.name);
68613
- const relativePath = path67.relative(workspace, fullPath);
68778
+ const fullPath = path68.join(dir, entry.name);
68779
+ const relativePath = path68.relative(workspace, fullPath);
68614
68780
  if (!validatePathForRead2(fullPath, workspace)) {
68615
68781
  continue;
68616
68782
  }
@@ -68651,7 +68817,7 @@ async function fallbackSearch(opts) {
68651
68817
  const matches = [];
68652
68818
  let total = 0;
68653
68819
  for (const file3 of files) {
68654
- const fullPath = path67.join(opts.workspace, file3);
68820
+ const fullPath = path68.join(opts.workspace, file3);
68655
68821
  if (!validatePathForRead2(fullPath, opts.workspace)) {
68656
68822
  continue;
68657
68823
  }
@@ -68822,7 +68988,7 @@ init_secretscan();
68822
68988
  init_tool();
68823
68989
  init_create_tool();
68824
68990
  import * as fs56 from "fs";
68825
- import * as path68 from "path";
68991
+ import * as path69 from "path";
68826
68992
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
68827
68993
  function containsWindowsAttacks4(str) {
68828
68994
  if (/:[^\\/]/.test(str))
@@ -68836,14 +69002,14 @@ function containsWindowsAttacks4(str) {
68836
69002
  }
68837
69003
  function isPathInWorkspace4(filePath, workspace) {
68838
69004
  try {
68839
- const resolvedPath = path68.resolve(workspace, filePath);
69005
+ const resolvedPath = path69.resolve(workspace, filePath);
68840
69006
  if (!fs56.existsSync(resolvedPath)) {
68841
69007
  return true;
68842
69008
  }
68843
69009
  const realWorkspace = fs56.realpathSync(workspace);
68844
69010
  const realResolvedPath = fs56.realpathSync(resolvedPath);
68845
- const relativePath = path68.relative(realWorkspace, realResolvedPath);
68846
- if (relativePath.startsWith("..") || path68.isAbsolute(relativePath)) {
69011
+ const relativePath = path69.relative(realWorkspace, realResolvedPath);
69012
+ if (relativePath.startsWith("..") || path69.isAbsolute(relativePath)) {
68847
69013
  return false;
68848
69014
  }
68849
69015
  return true;
@@ -69051,7 +69217,7 @@ var suggestPatch = createSwarmTool({
69051
69217
  });
69052
69218
  continue;
69053
69219
  }
69054
- const fullPath = path68.resolve(directory, change.file);
69220
+ const fullPath = path69.resolve(directory, change.file);
69055
69221
  if (!fs56.existsSync(fullPath)) {
69056
69222
  errors5.push({
69057
69223
  success: false,
@@ -69155,7 +69321,7 @@ init_dist();
69155
69321
  init_utils();
69156
69322
  init_create_tool();
69157
69323
  import * as fs57 from "fs";
69158
- import * as path69 from "path";
69324
+ import * as path70 from "path";
69159
69325
  var MAX_TEXT_LENGTH = 200;
69160
69326
  var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
69161
69327
  var SUPPORTED_EXTENSIONS2 = new Set([
@@ -69220,9 +69386,9 @@ function validatePathsInput(paths, cwd) {
69220
69386
  return { error: "paths contains path traversal", resolvedPath: null };
69221
69387
  }
69222
69388
  try {
69223
- const resolvedPath = path69.resolve(paths);
69224
- const normalizedCwd = path69.resolve(cwd);
69225
- const normalizedResolved = path69.resolve(resolvedPath);
69389
+ const resolvedPath = path70.resolve(paths);
69390
+ const normalizedCwd = path70.resolve(cwd);
69391
+ const normalizedResolved = path70.resolve(resolvedPath);
69226
69392
  if (!normalizedResolved.startsWith(normalizedCwd)) {
69227
69393
  return {
69228
69394
  error: "paths must be within the current working directory",
@@ -69238,7 +69404,7 @@ function validatePathsInput(paths, cwd) {
69238
69404
  }
69239
69405
  }
69240
69406
  function isSupportedExtension(filePath) {
69241
- const ext = path69.extname(filePath).toLowerCase();
69407
+ const ext = path70.extname(filePath).toLowerCase();
69242
69408
  return SUPPORTED_EXTENSIONS2.has(ext);
69243
69409
  }
69244
69410
  function findSourceFiles2(dir, files = []) {
@@ -69253,7 +69419,7 @@ function findSourceFiles2(dir, files = []) {
69253
69419
  if (SKIP_DIRECTORIES4.has(entry)) {
69254
69420
  continue;
69255
69421
  }
69256
- const fullPath = path69.join(dir, entry);
69422
+ const fullPath = path70.join(dir, entry);
69257
69423
  let stat2;
69258
69424
  try {
69259
69425
  stat2 = fs57.statSync(fullPath);
@@ -69365,7 +69531,7 @@ var todo_extract = createSwarmTool({
69365
69531
  filesToScan.push(scanPath);
69366
69532
  } else {
69367
69533
  const errorResult = {
69368
- error: `unsupported file extension: ${path69.extname(scanPath)}`,
69534
+ error: `unsupported file extension: ${path70.extname(scanPath)}`,
69369
69535
  total: 0,
69370
69536
  byPriority: { high: 0, medium: 0, low: 0 },
69371
69537
  entries: []
@@ -69412,14 +69578,14 @@ init_tool();
69412
69578
  init_schema();
69413
69579
  init_gate_evidence();
69414
69580
  import * as fs59 from "fs";
69415
- import * as path71 from "path";
69581
+ import * as path72 from "path";
69416
69582
 
69417
69583
  // src/hooks/diff-scope.ts
69418
69584
  import * as fs58 from "fs";
69419
- import * as path70 from "path";
69585
+ import * as path71 from "path";
69420
69586
  function getDeclaredScope(taskId, directory) {
69421
69587
  try {
69422
- const planPath = path70.join(directory, ".swarm", "plan.json");
69588
+ const planPath = path71.join(directory, ".swarm", "plan.json");
69423
69589
  if (!fs58.existsSync(planPath))
69424
69590
  return null;
69425
69591
  const raw = fs58.readFileSync(planPath, "utf-8");
@@ -69535,7 +69701,7 @@ var TIER_3_PATTERNS = [
69535
69701
  ];
69536
69702
  function matchesTier3Pattern(files) {
69537
69703
  for (const file3 of files) {
69538
- const fileName = path71.basename(file3);
69704
+ const fileName = path72.basename(file3);
69539
69705
  for (const pattern of TIER_3_PATTERNS) {
69540
69706
  if (pattern.test(fileName)) {
69541
69707
  return true;
@@ -69549,7 +69715,7 @@ function checkReviewerGate(taskId, workingDirectory) {
69549
69715
  if (hasActiveTurboMode()) {
69550
69716
  const resolvedDir2 = workingDirectory;
69551
69717
  try {
69552
- const planPath = path71.join(resolvedDir2, ".swarm", "plan.json");
69718
+ const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
69553
69719
  const planRaw = fs59.readFileSync(planPath, "utf-8");
69554
69720
  const plan = JSON.parse(planRaw);
69555
69721
  for (const planPhase of plan.phases ?? []) {
@@ -69616,7 +69782,7 @@ function checkReviewerGate(taskId, workingDirectory) {
69616
69782
  }
69617
69783
  try {
69618
69784
  const resolvedDir2 = workingDirectory;
69619
- const planPath = path71.join(resolvedDir2, ".swarm", "plan.json");
69785
+ const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
69620
69786
  const planRaw = fs59.readFileSync(planPath, "utf-8");
69621
69787
  const plan = JSON.parse(planRaw);
69622
69788
  for (const planPhase of plan.phases ?? []) {
@@ -69799,8 +69965,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
69799
69965
  };
69800
69966
  }
69801
69967
  }
69802
- normalizedDir = path71.normalize(args2.working_directory);
69803
- const pathParts = normalizedDir.split(path71.sep);
69968
+ normalizedDir = path72.normalize(args2.working_directory);
69969
+ const pathParts = normalizedDir.split(path72.sep);
69804
69970
  if (pathParts.includes("..")) {
69805
69971
  return {
69806
69972
  success: false,
@@ -69810,10 +69976,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
69810
69976
  ]
69811
69977
  };
69812
69978
  }
69813
- const resolvedDir = path71.resolve(normalizedDir);
69979
+ const resolvedDir = path72.resolve(normalizedDir);
69814
69980
  try {
69815
69981
  const realPath = fs59.realpathSync(resolvedDir);
69816
- const planPath = path71.join(realPath, ".swarm", "plan.json");
69982
+ const planPath = path72.join(realPath, ".swarm", "plan.json");
69817
69983
  if (!fs59.existsSync(planPath)) {
69818
69984
  return {
69819
69985
  success: false,
@@ -69847,7 +70013,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
69847
70013
  recoverTaskStateFromDelegations(args2.task_id);
69848
70014
  let phaseRequiresReviewer = true;
69849
70015
  try {
69850
- const planPath = path71.join(directory, ".swarm", "plan.json");
70016
+ const planPath = path72.join(directory, ".swarm", "plan.json");
69851
70017
  const planRaw = fs59.readFileSync(planPath, "utf-8");
69852
70018
  const plan = JSON.parse(planRaw);
69853
70019
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -69912,7 +70078,7 @@ init_tool();
69912
70078
  init_utils2();
69913
70079
  init_create_tool();
69914
70080
  import fs60 from "fs";
69915
- import path72 from "path";
70081
+ import path73 from "path";
69916
70082
  function normalizeVerdict(verdict) {
69917
70083
  switch (verdict) {
69918
70084
  case "APPROVED":
@@ -69959,7 +70125,7 @@ async function executeWriteDriftEvidence(args2, directory) {
69959
70125
  entries: [evidenceEntry]
69960
70126
  };
69961
70127
  const filename = "drift-verifier.json";
69962
- const relativePath = path72.join("evidence", String(phase), filename);
70128
+ const relativePath = path73.join("evidence", String(phase), filename);
69963
70129
  let validatedPath;
69964
70130
  try {
69965
70131
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -69970,10 +70136,10 @@ async function executeWriteDriftEvidence(args2, directory) {
69970
70136
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
69971
70137
  }, null, 2);
69972
70138
  }
69973
- const evidenceDir = path72.dirname(validatedPath);
70139
+ const evidenceDir = path73.dirname(validatedPath);
69974
70140
  try {
69975
70141
  await fs60.promises.mkdir(evidenceDir, { recursive: true });
69976
- const tempPath = path72.join(evidenceDir, `.${filename}.tmp`);
70142
+ const tempPath = path73.join(evidenceDir, `.${filename}.tmp`);
69977
70143
  await fs60.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
69978
70144
  await fs60.promises.rename(tempPath, validatedPath);
69979
70145
  return JSON.stringify({
@@ -70167,7 +70333,7 @@ var OpenCodeSwarm = async (ctx) => {
70167
70333
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
70168
70334
  preflightTriggerManager = new PTM(automationConfig);
70169
70335
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
70170
- const swarmDir = path73.resolve(ctx.directory, ".swarm");
70336
+ const swarmDir = path74.resolve(ctx.directory, ".swarm");
70171
70337
  statusArtifact = new ASA(swarmDir);
70172
70338
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
70173
70339
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {