trace-mcp 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -5,10 +5,16 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
8
14
  var __esm = (fn, res) => function __init() {
9
15
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
16
  };
11
- var __commonJS = (cb, mod) => function __require() {
17
+ var __commonJS = (cb, mod) => function __require2() {
12
18
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
19
  };
14
20
  var __export = (target, all) => {
@@ -1107,7 +1113,7 @@ var require_parse = __commonJS({
1107
1113
  }
1108
1114
  return { risky: false };
1109
1115
  };
1110
- var parse = (input, options) => {
1116
+ var parse2 = (input, options) => {
1111
1117
  if (typeof input !== "string") {
1112
1118
  throw new TypeError("Expected a string");
1113
1119
  }
@@ -1277,7 +1283,7 @@ var require_parse = __commonJS({
1277
1283
  output = token.close = `)$))${extglobStar}`;
1278
1284
  }
1279
1285
  if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
1280
- const expression = parse(rest, { ...options, fastpaths: false }).output;
1286
+ const expression = parse2(rest, { ...options, fastpaths: false }).output;
1281
1287
  output = token.close = `)${expression})${extglobStar})`;
1282
1288
  }
1283
1289
  if (token.prev.type === "bos") {
@@ -1799,7 +1805,7 @@ var require_parse = __commonJS({
1799
1805
  }
1800
1806
  return state;
1801
1807
  };
1802
- parse.fastpaths = (input, options) => {
1808
+ parse2.fastpaths = (input, options) => {
1803
1809
  const opts = { ...options };
1804
1810
  const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
1805
1811
  const len = input.length;
@@ -1864,7 +1870,7 @@ var require_parse = __commonJS({
1864
1870
  }
1865
1871
  return source;
1866
1872
  };
1867
- module.exports = parse;
1873
+ module.exports = parse2;
1868
1874
  }
1869
1875
  });
1870
1876
 
@@ -1873,7 +1879,7 @@ var require_picomatch = __commonJS({
1873
1879
  "node_modules/picomatch/lib/picomatch.js"(exports, module) {
1874
1880
  "use strict";
1875
1881
  var scan = require_scan();
1876
- var parse = require_parse();
1882
+ var parse2 = require_parse();
1877
1883
  var utils = require_utils();
1878
1884
  var constants = require_constants();
1879
1885
  var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
@@ -1961,7 +1967,7 @@ var require_picomatch = __commonJS({
1961
1967
  picomatch3.isMatch = (str2, patterns, options) => picomatch3(patterns, options)(str2);
1962
1968
  picomatch3.parse = (pattern, options) => {
1963
1969
  if (Array.isArray(pattern)) return pattern.map((p5) => picomatch3.parse(p5, options));
1964
- return parse(pattern, { ...options, fastpaths: false });
1970
+ return parse2(pattern, { ...options, fastpaths: false });
1965
1971
  };
1966
1972
  picomatch3.scan = (input, options) => scan(input, options);
1967
1973
  picomatch3.compileRe = (state, options, returnOutput = false, returnState = false) => {
@@ -1987,10 +1993,10 @@ var require_picomatch = __commonJS({
1987
1993
  }
1988
1994
  let parsed = { negated: false, fastpaths: true };
1989
1995
  if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
1990
- parsed.output = parse.fastpaths(input, options);
1996
+ parsed.output = parse2.fastpaths(input, options);
1991
1997
  }
1992
1998
  if (!parsed.output) {
1993
- parsed = parse(input, options);
1999
+ parsed = parse2(input, options);
1994
2000
  }
1995
2001
  return picomatch3.compileRe(parsed, options, returnOutput, returnState);
1996
2002
  };
@@ -2117,7 +2123,7 @@ var init_layer_violations = __esm({
2117
2123
  // src/cli.ts
2118
2124
  import { Command as Command12 } from "commander";
2119
2125
  import path107 from "path";
2120
- import fs96 from "fs";
2126
+ import fs97 from "fs";
2121
2127
  import { randomUUID } from "crypto";
2122
2128
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2123
2129
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -4377,7 +4383,7 @@ var PluginRegistry = class {
4377
4383
  // src/config.ts
4378
4384
  import { cosmiconfig } from "cosmiconfig";
4379
4385
  import { z } from "zod";
4380
- import fs2 from "fs";
4386
+ import fs3 from "fs";
4381
4387
 
4382
4388
  // src/global.ts
4383
4389
  import path from "path";
@@ -4420,9 +4426,9 @@ var DEFAULT_CONFIG_JSONC = `{
4420
4426
  "provider": "ollama", // "ollama" | "openai"
4421
4427
  // "base_url": "http://localhost:11434", // custom endpoint
4422
4428
  // "api_key": "", // required for openai; or set OPENAI_API_KEY env
4423
- // "inference_model": "", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
4424
- // "fast_model": "", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
4425
- // "embedding_model": "", // ollama: "qwen3-embedding:0.6b", openai: "text-embedding-3-small"
4429
+ "inference_model": "gemma4-e4b", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
4430
+ "fast_model": "gemma4-e4b", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
4431
+ "embedding_model": "qwen3-embedding:0.6b", // ollama: "qwen3-embedding:0.6b", openai: "text-embedding-3-small"
4426
4432
  // "embedding_dimensions": 1536, // provider-specific
4427
4433
  "summarize_on_index": true,
4428
4434
  "summarize_batch_size": 20,
@@ -4569,6 +4575,73 @@ function getDbPath(projectRoot) {
4569
4575
  return path.join(INDEX_DIR, `${projectName(absRoot)}-${projectHash(absRoot)}.db`);
4570
4576
  }
4571
4577
 
4578
+ // src/config-jsonc.ts
4579
+ import fs2 from "fs";
4580
+ import { modify, applyEdits, parse } from "jsonc-parser";
4581
+ var FORMAT_OPTS = {
4582
+ formattingOptions: {
4583
+ tabSize: 2,
4584
+ insertSpaces: true,
4585
+ eol: "\n"
4586
+ }
4587
+ };
4588
+ function readGlobalConfigText() {
4589
+ ensureGlobalDirs();
4590
+ if (!fs2.existsSync(GLOBAL_CONFIG_PATH)) return DEFAULT_CONFIG_JSONC;
4591
+ return fs2.readFileSync(GLOBAL_CONFIG_PATH, "utf-8");
4592
+ }
4593
+ function modifyGlobalConfigJsonc(jsonPath, value) {
4594
+ const text = readGlobalConfigText();
4595
+ const edits = modify(text, jsonPath, value, FORMAT_OPTS);
4596
+ const updated = applyEdits(text, edits);
4597
+ fs2.writeFileSync(GLOBAL_CONFIG_PATH, updated);
4598
+ }
4599
+ function saveProjectConfigJsonc(projectRoot, config) {
4600
+ ensureGlobalDirs();
4601
+ modifyGlobalConfigJsonc(["projects", projectRoot], config);
4602
+ }
4603
+ function removeProjectConfigJsonc(projectRoot) {
4604
+ modifyGlobalConfigJsonc(["projects", projectRoot], void 0);
4605
+ }
4606
+ function migrateGlobalConfig() {
4607
+ ensureGlobalDirs();
4608
+ const result = { added: [], changed: false };
4609
+ const existingText = readGlobalConfigText();
4610
+ const existing = parse(existingText);
4611
+ const defaults = parse(DEFAULT_CONFIG_JSONC);
4612
+ if (!existing || !defaults) return result;
4613
+ let text = existingText;
4614
+ for (const key of Object.keys(defaults)) {
4615
+ if (key in existing) {
4616
+ if (typeof defaults[key] === "object" && defaults[key] !== null && !Array.isArray(defaults[key]) && typeof existing[key] === "object" && existing[key] !== null && !Array.isArray(existing[key])) {
4617
+ const defaultSub = defaults[key];
4618
+ const existingSub = existing[key];
4619
+ for (const subKey of Object.keys(defaultSub)) {
4620
+ if (!(subKey in existingSub)) {
4621
+ const edits2 = modify(text, [key, subKey], defaultSub[subKey], FORMAT_OPTS);
4622
+ if (edits2.length > 0) {
4623
+ text = applyEdits(text, edits2);
4624
+ result.added.push(`${key}.${subKey}`);
4625
+ }
4626
+ }
4627
+ }
4628
+ }
4629
+ continue;
4630
+ }
4631
+ const edits = modify(text, [key], defaults[key], FORMAT_OPTS);
4632
+ if (edits.length > 0) {
4633
+ text = applyEdits(text, edits);
4634
+ result.added.push(key);
4635
+ }
4636
+ }
4637
+ if (text !== existingText) {
4638
+ fs2.writeFileSync(GLOBAL_CONFIG_PATH, text);
4639
+ result.changed = true;
4640
+ logger.info({ added: result.added }, "Migrated global config \u2014 added new keys");
4641
+ }
4642
+ return result;
4643
+ }
4644
+
4572
4645
  // src/config.ts
4573
4646
  var SecurityConfigSchema = z.object({
4574
4647
  secret_patterns: z.array(z.string()).optional(),
@@ -4772,9 +4845,9 @@ var TraceMcpConfigSchema = z.object({
4772
4845
  children: z.array(z.string()).optional()
4773
4846
  });
4774
4847
  function loadGlobalConfigRaw() {
4775
- if (!fs2.existsSync(GLOBAL_CONFIG_PATH)) return {};
4848
+ if (!fs3.existsSync(GLOBAL_CONFIG_PATH)) return {};
4776
4849
  try {
4777
- return JSON.parse(stripJsonComments(fs2.readFileSync(GLOBAL_CONFIG_PATH, "utf-8")));
4850
+ return JSON.parse(stripJsonComments(fs3.readFileSync(GLOBAL_CONFIG_PATH, "utf-8")));
4778
4851
  } catch {
4779
4852
  return {};
4780
4853
  }
@@ -4834,40 +4907,25 @@ async function loadConfig(searchFrom) {
4834
4907
  return err(configError(e instanceof Error ? e.message : String(e)));
4835
4908
  }
4836
4909
  }
4837
- function saveProjectConfig(projectRoot, config) {
4838
- ensureGlobalDirs();
4839
- const existing = loadGlobalConfigRaw();
4840
- const projects = existing.projects ?? {};
4841
- projects[projectRoot] = config;
4842
- existing.projects = projects;
4843
- fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(existing, null, 2) + "\n");
4844
- }
4845
- function removeProjectConfig(projectRoot) {
4846
- const existing = loadGlobalConfigRaw();
4847
- const projects = existing.projects ?? {};
4848
- delete projects[projectRoot];
4849
- existing.projects = projects;
4850
- fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(existing, null, 2) + "\n");
4851
- }
4852
4910
 
4853
4911
  // src/server/server.ts
4854
4912
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4855
4913
 
4856
4914
  // src/indexer/pipeline.ts
4857
- import fs11 from "fs";
4915
+ import fs12 from "fs";
4858
4916
  import path11 from "path";
4859
4917
  import { cpus } from "os";
4860
4918
  import fg3 from "fast-glob";
4861
4919
 
4862
4920
  // src/indexer/project-context.ts
4863
- import fs3 from "fs";
4921
+ import fs4 from "fs";
4864
4922
  import path2 from "path";
4865
4923
  function buildProjectContext(rootPath) {
4866
4924
  const detectedVersions = [];
4867
4925
  const allDependencies = [];
4868
4926
  const readFile = (rel) => {
4869
4927
  try {
4870
- return fs3.readFileSync(path2.resolve(rootPath, rel), "utf-8");
4928
+ return fs4.readFileSync(path2.resolve(rootPath, rel), "utf-8");
4871
4929
  } catch {
4872
4930
  return void 0;
4873
4931
  }
@@ -5181,14 +5239,14 @@ function buildProjectContext(rootPath) {
5181
5239
  ];
5182
5240
  for (const name of CONFIG_FILE_NAMES) {
5183
5241
  try {
5184
- fs3.accessSync(path2.resolve(rootPath, name));
5242
+ fs4.accessSync(path2.resolve(rootPath, name));
5185
5243
  configFiles.push(name);
5186
5244
  } catch {
5187
5245
  }
5188
5246
  }
5189
5247
  try {
5190
5248
  const ghWorkflowDir = path2.resolve(rootPath, ".github/workflows");
5191
- const entries = fs3.readdirSync(ghWorkflowDir);
5249
+ const entries = fs4.readdirSync(ghWorkflowDir);
5192
5250
  for (const entry of entries) {
5193
5251
  if (entry.endsWith(".yml") || entry.endsWith(".yaml")) {
5194
5252
  configFiles.push(`.github/workflows/${entry}`);
@@ -5214,7 +5272,7 @@ function buildProjectContext(rootPath) {
5214
5272
  }
5215
5273
 
5216
5274
  // src/indexer/monorepo.ts
5217
- import fs4 from "fs";
5275
+ import fs5 from "fs";
5218
5276
  import path3 from "path";
5219
5277
  import { parse as parseYaml } from "yaml";
5220
5278
  import fg from "fast-glob";
@@ -5230,7 +5288,7 @@ function detectWorkspaces(rootPath) {
5230
5288
  function buildMultiRootWorkspaces(parentDir, childRoots) {
5231
5289
  const workspaces = [];
5232
5290
  for (const childRoot of childRoots) {
5233
- if (!fs4.existsSync(childRoot)) {
5291
+ if (!fs5.existsSync(childRoot)) {
5234
5292
  logger.warn({ childRoot }, "Skipping missing multi-root child directory");
5235
5293
  continue;
5236
5294
  }
@@ -5249,9 +5307,9 @@ function buildMultiRootWorkspaces(parentDir, childRoots) {
5249
5307
  }
5250
5308
  function detectPnpmWorkspaces(rootPath) {
5251
5309
  const yamlPath = path3.join(rootPath, "pnpm-workspace.yaml");
5252
- if (!fs4.existsSync(yamlPath)) return [];
5310
+ if (!fs5.existsSync(yamlPath)) return [];
5253
5311
  try {
5254
- const content = fs4.readFileSync(yamlPath, "utf-8");
5312
+ const content = fs5.readFileSync(yamlPath, "utf-8");
5255
5313
  const parsed = parseYaml(content);
5256
5314
  if (!parsed?.packages?.length) return [];
5257
5315
  return expandGlobPatterns(rootPath, parsed.packages);
@@ -5262,9 +5320,9 @@ function detectPnpmWorkspaces(rootPath) {
5262
5320
  }
5263
5321
  function detectNpmWorkspaces(rootPath) {
5264
5322
  const pkgPath = path3.join(rootPath, "package.json");
5265
- if (!fs4.existsSync(pkgPath)) return [];
5323
+ if (!fs5.existsSync(pkgPath)) return [];
5266
5324
  try {
5267
- const content = fs4.readFileSync(pkgPath, "utf-8");
5325
+ const content = fs5.readFileSync(pkgPath, "utf-8");
5268
5326
  const pkg = JSON.parse(content);
5269
5327
  let patterns;
5270
5328
  if (Array.isArray(pkg.workspaces)) {
@@ -5281,9 +5339,9 @@ function detectNpmWorkspaces(rootPath) {
5281
5339
  }
5282
5340
  function detectComposerWorkspaces(rootPath) {
5283
5341
  const composerPath = path3.join(rootPath, "composer.json");
5284
- if (!fs4.existsSync(composerPath)) return [];
5342
+ if (!fs5.existsSync(composerPath)) return [];
5285
5343
  try {
5286
- const content = fs4.readFileSync(composerPath, "utf-8");
5344
+ const content = fs5.readFileSync(composerPath, "utf-8");
5287
5345
  const composer = JSON.parse(content);
5288
5346
  if (!composer.repositories?.length) return [];
5289
5347
  const pathRepos = composer.repositories.filter((r) => r.type === "path" && r.url);
@@ -5308,8 +5366,8 @@ function expandGlobPatterns(rootPath, patterns) {
5308
5366
  for (const match of matches) {
5309
5367
  const relPath = match.replace(/\\/g, "/");
5310
5368
  if (seen.has(relPath)) continue;
5311
- const hasPackageJson = fs4.existsSync(path3.join(rootPath, relPath, "package.json"));
5312
- const hasComposerJson = fs4.existsSync(path3.join(rootPath, relPath, "composer.json"));
5369
+ const hasPackageJson = fs5.existsSync(path3.join(rootPath, relPath, "package.json"));
5370
+ const hasComposerJson = fs5.existsSync(path3.join(rootPath, relPath, "composer.json"));
5313
5371
  if (!hasPackageJson && !hasComposerJson) continue;
5314
5372
  const name = resolveWorkspaceName(rootPath, relPath);
5315
5373
  seen.add(relPath);
@@ -5321,16 +5379,16 @@ function expandGlobPatterns(rootPath, patterns) {
5321
5379
  function resolveWorkspaceName(rootPath, relPath) {
5322
5380
  try {
5323
5381
  const pkgPath = path3.join(rootPath, relPath, "package.json");
5324
- if (fs4.existsSync(pkgPath)) {
5325
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
5382
+ if (fs5.existsSync(pkgPath)) {
5383
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
5326
5384
  if (pkg.name) return pkg.name;
5327
5385
  }
5328
5386
  } catch {
5329
5387
  }
5330
5388
  try {
5331
5389
  const composerPath = path3.join(rootPath, relPath, "composer.json");
5332
- if (fs4.existsSync(composerPath)) {
5333
- const composer = JSON.parse(fs4.readFileSync(composerPath, "utf-8"));
5390
+ if (fs5.existsSync(composerPath)) {
5391
+ const composer = JSON.parse(fs5.readFileSync(composerPath, "utf-8"));
5334
5392
  if (composer.name) return composer.name;
5335
5393
  }
5336
5394
  } catch {
@@ -5456,7 +5514,7 @@ function isBinaryBuffer(buf) {
5456
5514
  }
5457
5515
 
5458
5516
  // src/utils/gitignore.ts
5459
- import fs5 from "fs";
5517
+ import fs6 from "fs";
5460
5518
  import path5 from "path";
5461
5519
 
5462
5520
  // src/utils/ignore-patterns.ts
@@ -5520,9 +5578,9 @@ var GitignoreMatcher = class {
5520
5578
  }
5521
5579
  loadGitignore(rootPath) {
5522
5580
  const gitignorePath = path5.join(rootPath, ".gitignore");
5523
- if (!fs5.existsSync(gitignorePath)) return;
5581
+ if (!fs6.existsSync(gitignorePath)) return;
5524
5582
  try {
5525
- const content = fs5.readFileSync(gitignorePath, "utf-8");
5583
+ const content = fs6.readFileSync(gitignorePath, "utf-8");
5526
5584
  const lines = content.split("\n");
5527
5585
  for (const line of lines) {
5528
5586
  const rule = parseIgnorePattern(line);
@@ -5548,7 +5606,7 @@ var GitignoreMatcher = class {
5548
5606
  };
5549
5607
 
5550
5608
  // src/utils/traceignore.ts
5551
- import fs6 from "fs";
5609
+ import fs7 from "fs";
5552
5610
  import path6 from "path";
5553
5611
  var TraceignoreMatcher = class _TraceignoreMatcher {
5554
5612
  rules = [];
@@ -5584,9 +5642,9 @@ var TraceignoreMatcher = class _TraceignoreMatcher {
5584
5642
  }
5585
5643
  loadTraceignore(rootPath) {
5586
5644
  const traceignorePath = path6.join(rootPath, ".traceignore");
5587
- if (!fs6.existsSync(traceignorePath)) return;
5645
+ if (!fs7.existsSync(traceignorePath)) return;
5588
5646
  try {
5589
- const content = fs6.readFileSync(traceignorePath, "utf-8");
5647
+ const content = fs7.readFileSync(traceignorePath, "utf-8");
5590
5648
  const lines = content.split("\n");
5591
5649
  for (const line of lines) {
5592
5650
  const rule = parseIgnorePattern(line);
@@ -6905,7 +6963,7 @@ function resolveTypeScriptHeritageEdges(state) {
6905
6963
  }
6906
6964
 
6907
6965
  // src/indexer/edge-resolvers/imports.ts
6908
- import fs7 from "fs";
6966
+ import fs8 from "fs";
6909
6967
  import path8 from "path";
6910
6968
 
6911
6969
  // src/indexer/resolvers/es-modules.ts
@@ -6945,7 +7003,7 @@ function resolveEsmImportEdges(state) {
6945
7003
  if (state.pendingImports.size === 0) return;
6946
7004
  let resolver;
6947
7005
  try {
6948
- const tsconfigPath = fs7.existsSync(path8.join(state.rootPath, "tsconfig.json")) ? path8.join(state.rootPath, "tsconfig.json") : void 0;
7006
+ const tsconfigPath = fs8.existsSync(path8.join(state.rootPath, "tsconfig.json")) ? path8.join(state.rootPath, "tsconfig.json") : void 0;
6949
7007
  resolver = new EsModuleResolver(state.rootPath, tsconfigPath);
6950
7008
  } catch {
6951
7009
  logger.warn("EsModuleResolver init failed \u2014 skipping import edge resolution");
@@ -7271,12 +7329,12 @@ var EdgeResolver = class {
7271
7329
  };
7272
7330
 
7273
7331
  // src/indexer/file-extractor.ts
7274
- import fs9 from "fs";
7332
+ import fs10 from "fs";
7275
7333
  import path9 from "path";
7276
7334
 
7277
7335
  // src/utils/hasher.ts
7278
7336
  import crypto2 from "crypto";
7279
- import fs8 from "fs";
7337
+ import fs9 from "fs";
7280
7338
  function hashContent(content) {
7281
7339
  return crypto2.createHash("md5").update(content).digest("hex");
7282
7340
  }
@@ -7297,7 +7355,7 @@ var FileExtractor = class {
7297
7355
  }
7298
7356
  let fileMtimeMs = null;
7299
7357
  try {
7300
- const stat = fs9.lstatSync(absPath);
7358
+ const stat = fs10.lstatSync(absPath);
7301
7359
  if (stat.isSymbolicLink()) {
7302
7360
  logger.warn({ file: relPath }, "Symlink skipped");
7303
7361
  return "error";
@@ -7315,7 +7373,7 @@ var FileExtractor = class {
7315
7373
  }
7316
7374
  let content;
7317
7375
  try {
7318
- content = fs9.readFileSync(absPath);
7376
+ content = fs10.readFileSync(absPath);
7319
7377
  } catch {
7320
7378
  logger.warn({ file: relPath }, "Cannot read file");
7321
7379
  return "error";
@@ -7449,7 +7507,7 @@ var FileExtractor = class {
7449
7507
  };
7450
7508
 
7451
7509
  // src/indexer/env-indexer.ts
7452
- import fs10 from "fs";
7510
+ import fs11 from "fs";
7453
7511
  import path10 from "path";
7454
7512
  import fg2 from "fast-glob";
7455
7513
 
@@ -7579,7 +7637,7 @@ var EnvIndexer = class {
7579
7637
  if (pathCheck.isErr()) continue;
7580
7638
  let content;
7581
7639
  try {
7582
- content = fs10.readFileSync(absPath, "utf-8");
7640
+ content = fs11.readFileSync(absPath, "utf-8");
7583
7641
  } catch {
7584
7642
  logger.warn({ file: relPath }, "Cannot read .env file");
7585
7643
  continue;
@@ -7846,7 +7904,7 @@ var IndexingPipeline = class _IndexingPipeline {
7846
7904
  const cached = this._fileContentCache.get(relPath);
7847
7905
  if (cached !== void 0) return cached;
7848
7906
  try {
7849
- return fs11.readFileSync(path11.resolve(this.rootPath, relPath), "utf-8");
7907
+ return fs12.readFileSync(path11.resolve(this.rootPath, relPath), "utf-8");
7850
7908
  } catch {
7851
7909
  return void 0;
7852
7910
  }
@@ -8657,7 +8715,7 @@ Respond with one score per line, in order: just the number, nothing else.`;
8657
8715
  };
8658
8716
 
8659
8717
  // src/ai/summarization-pipeline.ts
8660
- import fs12 from "fs";
8718
+ import fs13 from "fs";
8661
8719
  import path12 from "path";
8662
8720
  var MAX_SOURCE_LINES = 80;
8663
8721
  var SummarizationPipeline = class {
@@ -8752,7 +8810,7 @@ var SummarizationPipeline = class {
8752
8810
  readSource(filePath, byteStart, byteEnd) {
8753
8811
  try {
8754
8812
  const absPath = path12.resolve(this.rootPath, filePath);
8755
- const content = fs12.readFileSync(absPath, "utf-8");
8813
+ const content = fs13.readFileSync(absPath, "utf-8");
8756
8814
  const slice = content.slice(byteStart, byteEnd);
8757
8815
  const lines = slice.split("\n");
8758
8816
  if (lines.length > MAX_SOURCE_LINES) {
@@ -9290,7 +9348,7 @@ function withHints(toolName, result) {
9290
9348
  }
9291
9349
 
9292
9350
  // src/savings.ts
9293
- import fs13 from "fs";
9351
+ import fs14 from "fs";
9294
9352
  import path13 from "path";
9295
9353
  var SAVINGS_PATH = path13.join(TRACE_MCP_HOME, "savings.json");
9296
9354
  var RAW_COST_ESTIMATES = {
@@ -9409,8 +9467,8 @@ var SavingsTracker = class {
9409
9467
  };
9410
9468
  function loadPersistentSavings() {
9411
9469
  try {
9412
- if (!fs13.existsSync(SAVINGS_PATH)) return null;
9413
- const raw = JSON.parse(fs13.readFileSync(SAVINGS_PATH, "utf-8"));
9470
+ if (!fs14.existsSync(SAVINGS_PATH)) return null;
9471
+ const raw = JSON.parse(fs14.readFileSync(SAVINGS_PATH, "utf-8"));
9414
9472
  if (raw.version !== 1) return null;
9415
9473
  return raw;
9416
9474
  } catch {
@@ -9419,13 +9477,13 @@ function loadPersistentSavings() {
9419
9477
  }
9420
9478
  function savePersistentSavings(data) {
9421
9479
  const tmpPath = SAVINGS_PATH + ".tmp";
9422
- fs13.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n");
9423
- fs13.renameSync(tmpPath, SAVINGS_PATH);
9480
+ fs14.writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n");
9481
+ fs14.renameSync(tmpPath, SAVINGS_PATH);
9424
9482
  }
9425
9483
 
9426
9484
  // src/session/journal.ts
9427
9485
  import { createHash as createHash2 } from "crypto";
9428
- import fs14 from "fs";
9486
+ import fs15 from "fs";
9429
9487
  import path14 from "path";
9430
9488
  var SessionJournal = class _SessionJournal {
9431
9489
  entries = [];
@@ -9749,8 +9807,8 @@ var SessionJournal = class _SessionJournal {
9749
9807
  if (this.entries.length === 0) return;
9750
9808
  const snapshot = this.getSnapshot();
9751
9809
  const dir = path14.dirname(snapshotPath);
9752
- if (!fs14.existsSync(dir)) fs14.mkdirSync(dir, { recursive: true });
9753
- fs14.writeFileSync(snapshotPath, JSON.stringify({
9810
+ if (!fs15.existsSync(dir)) fs15.mkdirSync(dir, { recursive: true });
9811
+ fs15.writeFileSync(snapshotPath, JSON.stringify({
9754
9812
  timestamp: Date.now(),
9755
9813
  markdown: snapshot.snapshot,
9756
9814
  structured: snapshot.structured,
@@ -9781,7 +9839,7 @@ var SessionJournal = class _SessionJournal {
9781
9839
  };
9782
9840
 
9783
9841
  // src/session/resume.ts
9784
- import fs15 from "fs";
9842
+ import fs16 from "fs";
9785
9843
  import path15 from "path";
9786
9844
  var SESSIONS_DIR = path15.join(TRACE_MCP_HOME, "sessions");
9787
9845
  var MAX_SESSIONS = 20;
@@ -9791,8 +9849,8 @@ function getSessionsPath(projectRoot) {
9791
9849
  function loadSessions(projectRoot) {
9792
9850
  try {
9793
9851
  const filePath = getSessionsPath(projectRoot);
9794
- if (!fs15.existsSync(filePath)) return [];
9795
- const data = JSON.parse(fs15.readFileSync(filePath, "utf-8"));
9852
+ if (!fs16.existsSync(filePath)) return [];
9853
+ const data = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
9796
9854
  return Array.isArray(data) ? data : [];
9797
9855
  } catch {
9798
9856
  return [];
@@ -9801,10 +9859,10 @@ function loadSessions(projectRoot) {
9801
9859
  function saveSessions(projectRoot, sessions) {
9802
9860
  try {
9803
9861
  ensureGlobalDirs();
9804
- fs15.mkdirSync(SESSIONS_DIR, { recursive: true });
9862
+ fs16.mkdirSync(SESSIONS_DIR, { recursive: true });
9805
9863
  const filePath = getSessionsPath(projectRoot);
9806
9864
  const trimmed = sessions.slice(-MAX_SESSIONS);
9807
- fs15.writeFileSync(filePath, JSON.stringify(trimmed, null, 2));
9865
+ fs16.writeFileSync(filePath, JSON.stringify(trimmed, null, 2));
9808
9866
  } catch (e) {
9809
9867
  logger.warn({ error: e }, "Failed to save session summary");
9810
9868
  }
@@ -9886,7 +9944,7 @@ function getSessionResume(projectRoot, maxSessions = 5) {
9886
9944
  }
9887
9945
 
9888
9946
  // src/server/file-watcher.ts
9889
- import fs16 from "fs";
9947
+ import fs17 from "fs";
9890
9948
  import path16 from "path";
9891
9949
  var FileWatcher = class {
9892
9950
  watcher = null;
@@ -9906,7 +9964,7 @@ var FileWatcher = class {
9906
9964
  }
9907
9965
  start() {
9908
9966
  try {
9909
- this.watcher = fs16.watch(this.projectRoot, { recursive: true }, (_event, filename) => {
9967
+ this.watcher = fs17.watch(this.projectRoot, { recursive: true }, (_event, filename) => {
9910
9968
  if (!filename) return;
9911
9969
  if (this.shouldIgnore(filename)) return;
9912
9970
  if (this.extensions.size > 0) {
@@ -9956,7 +10014,7 @@ var FileWatcher = class {
9956
10014
  };
9957
10015
 
9958
10016
  // src/server/explored-tracker.ts
9959
- import fs17 from "fs";
10017
+ import fs18 from "fs";
9960
10018
  import path17 from "path";
9961
10019
  import os2 from "os";
9962
10020
  import crypto3 from "crypto";
@@ -9964,7 +10022,7 @@ function createExploredTracker(projectRoot) {
9964
10022
  const hash = crypto3.createHash("sha256").update(projectRoot).digest("hex").slice(0, 12);
9965
10023
  const markerDir2 = path17.join(os2.tmpdir(), `trace-mcp-explored-${hash}`);
9966
10024
  try {
9967
- fs17.mkdirSync(markerDir2, { recursive: true });
10025
+ fs18.mkdirSync(markerDir2, { recursive: true });
9968
10026
  } catch {
9969
10027
  }
9970
10028
  return {
@@ -9972,7 +10030,7 @@ function createExploredTracker(projectRoot) {
9972
10030
  const absPath = path17.isAbsolute(filePath) ? filePath : path17.resolve(projectRoot, filePath);
9973
10031
  const fileHash2 = crypto3.createHash("sha256").update(absPath).digest("hex");
9974
10032
  try {
9975
- fs17.writeFileSync(path17.join(markerDir2, fileHash2), absPath);
10033
+ fs18.writeFileSync(path17.join(markerDir2, fileHash2), absPath);
9976
10034
  } catch {
9977
10035
  }
9978
10036
  }
@@ -10062,7 +10120,7 @@ function buildInstructions(detectedFrameworks, verbosity) {
10062
10120
  }
10063
10121
 
10064
10122
  // src/server/consultation-markers.ts
10065
- import fs18 from "fs";
10123
+ import fs19 from "fs";
10066
10124
  import path18 from "path";
10067
10125
  import os3 from "os";
10068
10126
  import crypto4 from "crypto";
@@ -10075,8 +10133,8 @@ function markerDir(projectRoot) {
10075
10133
  function markConsulted(projectRoot, relPath) {
10076
10134
  try {
10077
10135
  const dir = markerDir(projectRoot);
10078
- fs18.mkdirSync(dir, { recursive: true });
10079
- fs18.writeFileSync(path18.join(dir, fileHash(relPath)), "", { flag: "w" });
10136
+ fs19.mkdirSync(dir, { recursive: true });
10137
+ fs19.writeFileSync(path18.join(dir, fileHash(relPath)), "", { flag: "w" });
10080
10138
  } catch {
10081
10139
  }
10082
10140
  }
@@ -10694,20 +10752,20 @@ import { z as z3 } from "zod";
10694
10752
  import path20 from "path";
10695
10753
 
10696
10754
  // src/utils/source-reader.ts
10697
- import fs19 from "fs";
10755
+ import fs20 from "fs";
10698
10756
  import path19 from "path";
10699
10757
  var GITIGNORED_NOTICE = "[content hidden \u2014 file is gitignored]";
10700
10758
  function readByteRange(filePath, byteStart, byteEnd, gitignored) {
10701
10759
  if (gitignored && !isEnvFile(filePath)) return GITIGNORED_NOTICE;
10702
10760
  if (byteEnd <= byteStart || byteStart < 0) return "";
10703
- const fd = fs19.openSync(filePath, "r");
10761
+ const fd = fs20.openSync(filePath, "r");
10704
10762
  try {
10705
10763
  const length = byteEnd - byteStart;
10706
10764
  const buffer = Buffer.alloc(length);
10707
- const bytesRead = fs19.readSync(fd, buffer, 0, length, byteStart);
10765
+ const bytesRead = fs20.readSync(fd, buffer, 0, length, byteStart);
10708
10766
  return buffer.subarray(0, bytesRead).toString("utf8");
10709
10767
  } finally {
10710
- fs19.closeSync(fd);
10768
+ fs20.closeSync(fd);
10711
10769
  }
10712
10770
  }
10713
10771
  var ENV_BASENAME_RE = /^\.env(\..+)?$/;
@@ -11767,10 +11825,34 @@ var DEFAULT_WEIGHTS = { primary: 0.4, dependencies: 0.3, callers: 0.2, typeConte
11767
11825
  function assembleStructuredContext(request) {
11768
11826
  const weights = request.budgetWeights ?? DEFAULT_WEIGHTS;
11769
11827
  const budget = request.totalBudget;
11770
- const primaryResult = assembleContext(request.primary, Math.floor(budget * weights.primary));
11771
- const depsResult = assembleContext(request.dependencies, Math.floor(budget * weights.dependencies));
11772
- const callersResult = assembleContext(request.callers, Math.floor(budget * weights.callers));
11773
- const typeResult = assembleContext(request.typeContext, Math.floor(budget * weights.typeContext));
11828
+ const categories = ["primary", "dependencies", "callers", "typeContext"];
11829
+ const itemCounts = {
11830
+ primary: request.primary.length,
11831
+ dependencies: request.dependencies.length,
11832
+ callers: request.callers.length,
11833
+ typeContext: request.typeContext.length
11834
+ };
11835
+ let surplusWeight = 0;
11836
+ let activeWeight = 0;
11837
+ for (const cat of categories) {
11838
+ if (itemCounts[cat] === 0) {
11839
+ surplusWeight += weights[cat];
11840
+ } else {
11841
+ activeWeight += weights[cat];
11842
+ }
11843
+ }
11844
+ const effectiveWeights = { primary: 0, dependencies: 0, callers: 0, typeContext: 0 };
11845
+ for (const cat of categories) {
11846
+ if (itemCounts[cat] === 0) {
11847
+ effectiveWeights[cat] = 0;
11848
+ } else if (activeWeight > 0) {
11849
+ effectiveWeights[cat] = weights[cat] + surplusWeight * (weights[cat] / activeWeight);
11850
+ }
11851
+ }
11852
+ const primaryResult = assembleContext(request.primary, Math.floor(budget * effectiveWeights.primary));
11853
+ const depsResult = assembleContext(request.dependencies, Math.floor(budget * effectiveWeights.dependencies));
11854
+ const callersResult = assembleContext(request.callers, Math.floor(budget * effectiveWeights.callers));
11855
+ const typeResult = assembleContext(request.typeContext, Math.floor(budget * effectiveWeights.typeContext));
11774
11856
  return {
11775
11857
  primary: primaryResult.items,
11776
11858
  dependencies: depsResult.items,
@@ -11813,19 +11895,34 @@ var CALL_EDGES = /* @__PURE__ */ new Set([
11813
11895
  "nest_injects",
11814
11896
  "graphql_resolves"
11815
11897
  ]);
11816
- function readSource(sym, file, rootPath) {
11817
- try {
11818
- const absPath = path22.resolve(rootPath, file.path);
11819
- return readByteRange(absPath, sym.byte_start, sym.byte_end, !!file.gitignored) ?? void 0;
11820
- } catch {
11821
- return void 0;
11898
+ var FileReadCache = class {
11899
+ constructor(rootPath) {
11900
+ this.rootPath = rootPath;
11822
11901
  }
11823
- }
11824
- function toContextItem(sym, file, rootPath, score) {
11902
+ rootPath;
11903
+ cache = /* @__PURE__ */ new Map();
11904
+ readSymbolSource(sym, file) {
11905
+ let buf = this.cache.get(file.id);
11906
+ if (buf === void 0) {
11907
+ try {
11908
+ const absPath = path22.resolve(this.rootPath, file.path);
11909
+ const fs98 = __require("fs");
11910
+ buf = fs98.readFileSync(absPath);
11911
+ } catch {
11912
+ buf = null;
11913
+ }
11914
+ this.cache.set(file.id, buf);
11915
+ }
11916
+ if (!buf || sym.byte_start == null || sym.byte_end == null) return void 0;
11917
+ if (file.gitignored) return "[gitignored]";
11918
+ return buf.subarray(sym.byte_start, sym.byte_end).toString("utf-8");
11919
+ }
11920
+ };
11921
+ function toContextItemCached(sym, file, cache, score, signatureOnly) {
11825
11922
  return {
11826
11923
  id: sym.symbol_id,
11827
11924
  score,
11828
- source: readSource(sym, file, rootPath),
11925
+ source: signatureOnly ? void 0 : cache.readSymbolSource(sym, file),
11829
11926
  signature: sym.signature ?? void 0,
11830
11927
  metadata: `[${sym.kind}] ${sym.fqn ?? sym.name} \u2014 ${file.path}`
11831
11928
  };
@@ -11936,14 +12033,16 @@ function getContextBundle(store, rootPath, opts) {
11936
12033
  }
11937
12034
  }
11938
12035
  }
12036
+ const fileCache = new FileReadCache(rootPath);
11939
12037
  const primaryItems = primarySymbols.map(
11940
- (p5, i) => toContextItem(p5.sym, p5.file, rootPath, 1 - i * 0.01)
12038
+ (p5, i) => toContextItemCached(p5.sym, p5.file, fileCache, 1 - i * 0.01, false)
11941
12039
  );
12040
+ const MAX_FULL_SOURCE_DEPS = 10;
11942
12041
  const depItems = depSymbols.map(
11943
- (d, i) => toContextItem(d.sym, d.file, rootPath, 0.8 - i * 5e-3)
12042
+ (d, i) => toContextItemCached(d.sym, d.file, fileCache, 0.8 - i * 5e-3, i >= MAX_FULL_SOURCE_DEPS)
11944
12043
  );
11945
12044
  const callerItems = callerSymbols.map(
11946
- (c, i) => toContextItem(c.sym, c.file, rootPath, 0.6 - i * 5e-3)
12045
+ (c, i) => toContextItemCached(c.sym, c.file, fileCache, 0.6 - i * 5e-3, i >= MAX_FULL_SOURCE_DEPS)
11947
12046
  );
11948
12047
  const assembled = assembleStructuredContext({
11949
12048
  primary: primaryItems,
@@ -12530,7 +12629,7 @@ function buildNegativeEvidence(indexedFiles, indexedSymbols, queryExpanded, tool
12530
12629
  }
12531
12630
 
12532
12631
  // src/tools/navigation/search-text.ts
12533
- import fs20 from "fs";
12632
+ import fs21 from "fs";
12534
12633
  import path24 from "path";
12535
12634
  var import_picomatch = __toESM(require_picomatch2(), 1);
12536
12635
  function searchText(store, projectRoot, opts) {
@@ -12580,9 +12679,9 @@ function searchText(store, projectRoot, opts) {
12580
12679
  if (pathCheck.isErr()) continue;
12581
12680
  let content;
12582
12681
  try {
12583
- const stat = fs20.statSync(absPath);
12682
+ const stat = fs21.statSync(absPath);
12584
12683
  if (stat.size > 1048576) continue;
12585
- content = fs20.readFileSync(absPath, "utf-8");
12684
+ content = fs21.readFileSync(absPath, "utf-8");
12586
12685
  } catch {
12587
12686
  continue;
12588
12687
  }
@@ -13359,7 +13458,7 @@ function splitControllerRef(ref) {
13359
13458
  }
13360
13459
 
13361
13460
  // src/tools/framework/middleware-chain.ts
13362
- import fs21 from "fs";
13461
+ import fs22 from "fs";
13363
13462
  import path26 from "path";
13364
13463
  function getMiddlewareChain(store, rootPath, url) {
13365
13464
  const allRoutes = store.getAllRoutes();
@@ -13407,9 +13506,9 @@ function detectFramework(allFiles) {
13407
13506
  }
13408
13507
  return "unknown";
13409
13508
  }
13410
- function readSource2(rootPath, filePath) {
13509
+ function readSource(rootPath, filePath) {
13411
13510
  try {
13412
- return fs21.readFileSync(path26.resolve(rootPath, filePath), "utf-8");
13511
+ return fs22.readFileSync(path26.resolve(rootPath, filePath), "utf-8");
13413
13512
  } catch {
13414
13513
  return void 0;
13415
13514
  }
@@ -13419,7 +13518,7 @@ function buildExpressChain(store, rootPath, url, allFiles, chain) {
13419
13518
  const PATH_MW_RE = /(?:app|router)\s*\.\s*use\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*([A-Za-z][\w.]*)/g;
13420
13519
  for (const file of allFiles) {
13421
13520
  if (file.framework_role !== "express_router" && file.framework_role !== "express_middleware") continue;
13422
- const source = readSource2(rootPath, file.path);
13521
+ const source = readSource(rootPath, file.path);
13423
13522
  if (!source) continue;
13424
13523
  let match;
13425
13524
  const globalRe2 = new RegExp(GLOBAL_MW_RE.source, "g");
@@ -13444,7 +13543,7 @@ function buildNestChain(store, rootPath, route, allFiles, chain) {
13444
13543
  const FILTERS_RE = /@UseFilters\(\s*([^)]+)\s*\)/g;
13445
13544
  const controllerFiles = allFiles.filter((f) => f.framework_role === "nest_controller");
13446
13545
  for (const file of controllerFiles) {
13447
- const source = readSource2(rootPath, file.path);
13546
+ const source = readSource(rootPath, file.path);
13448
13547
  if (!source) continue;
13449
13548
  const extractDecorators2 = (regex, scope) => {
13450
13549
  const re = new RegExp(regex.source, "g");
@@ -13497,7 +13596,7 @@ function buildFlaskChain(store, rootPath, url, allFiles, chain) {
13497
13596
  }
13498
13597
  for (const file of allFiles) {
13499
13598
  if (file.framework_role !== "flask_routes") continue;
13500
- const source = readSource2(rootPath, file.path);
13599
+ const source = readSource(rootPath, file.path);
13501
13600
  if (!source) continue;
13502
13601
  const decoratorRe = /@([\w.]+)\s*(?:\([^)]*\))?\s*\n\s*(?:@\w[\w.]*\s*(?:\([^)]*\))?\s*\n\s*)*def\s+\w+/g;
13503
13602
  let m;
@@ -13512,7 +13611,7 @@ function buildFlaskChain(store, rootPath, url, allFiles, chain) {
13512
13611
  function buildFastAPIChain(store, rootPath, url, allFiles, chain) {
13513
13612
  for (const file of allFiles) {
13514
13613
  if (file.framework_role !== "fastapi_routes" && file.framework_role !== "fastapi_app") continue;
13515
- const source = readSource2(rootPath, file.path);
13614
+ const source = readSource(rootPath, file.path);
13516
13615
  if (!source) continue;
13517
13616
  const addMwRe = /(?:app|router)\s*\.\s*add_middleware\s*\(\s*([\w.]+)/g;
13518
13617
  let m;
@@ -13540,7 +13639,7 @@ function buildFastAPIChain(store, rootPath, url, allFiles, chain) {
13540
13639
  function buildDjangoChain(store, rootPath, allFiles, chain) {
13541
13640
  for (const file of allFiles) {
13542
13641
  if (!file.path.endsWith("settings.py") && !file.path.includes("settings/")) continue;
13543
- const source = readSource2(rootPath, file.path);
13642
+ const source = readSource(rootPath, file.path);
13544
13643
  if (!source) continue;
13545
13644
  const mwMatch = source.match(/MIDDLEWARE\s*=\s*\[([\s\S]*?)\]/);
13546
13645
  if (!mwMatch) continue;
@@ -13554,7 +13653,7 @@ function buildDjangoChain(store, rootPath, allFiles, chain) {
13554
13653
  }
13555
13654
  for (const file of allFiles) {
13556
13655
  if (file.framework_role !== "view") continue;
13557
- const source = readSource2(rootPath, file.path);
13656
+ const source = readSource(rootPath, file.path);
13558
13657
  if (!source) continue;
13559
13658
  const decoratorRe = /@([\w.]+)\s*(?:\([^)]*\))?\s*\n\s*(?:@\w[\w.]*\s*(?:\([^)]*\))?\s*\n\s*)*(?:def|class)\s+\w+/g;
13560
13659
  let m;
@@ -13567,11 +13666,11 @@ function buildDjangoChain(store, rootPath, allFiles, chain) {
13567
13666
  }
13568
13667
 
13569
13668
  // src/tools/analysis/module-graph.ts
13570
- import fs23 from "fs";
13669
+ import fs24 from "fs";
13571
13670
  import path28 from "path";
13572
13671
 
13573
13672
  // src/indexer/plugins/integration/framework/nestjs/index.ts
13574
- import fs22 from "fs";
13673
+ import fs23 from "fs";
13575
13674
  import path27 from "path";
13576
13675
  var HTTP_METHODS = ["Get", "Post", "Put", "Delete", "Patch", "Head", "Options"];
13577
13676
  var CONTROLLER_RE = /@Controller\(\s*['"`]([^'"`]*)['"`]\s*\)/;
@@ -13688,7 +13787,7 @@ var NestJSPlugin = class {
13688
13787
  }
13689
13788
  try {
13690
13789
  const pkgPath = path27.join(ctx.rootPath, "package.json");
13691
- const content = fs22.readFileSync(pkgPath, "utf-8");
13790
+ const content = fs23.readFileSync(pkgPath, "utf-8");
13692
13791
  const pkg = JSON.parse(content);
13693
13792
  const deps = {
13694
13793
  ...pkg.dependencies,
@@ -13841,7 +13940,7 @@ function getModuleGraph(store, rootPath, moduleName) {
13841
13940
  for (const file of moduleFiles) {
13842
13941
  let source;
13843
13942
  try {
13844
- source = fs23.readFileSync(path28.resolve(rootPath, file.path), "utf-8");
13943
+ source = fs24.readFileSync(path28.resolve(rootPath, file.path), "utf-8");
13845
13944
  } catch {
13846
13945
  continue;
13847
13946
  }
@@ -19229,14 +19328,14 @@ function registerGitTools(server, ctx) {
19229
19328
  import { z as z7 } from "zod";
19230
19329
 
19231
19330
  // src/tools/refactoring/refactor.ts
19232
- import fs24 from "fs";
19331
+ import fs25 from "fs";
19233
19332
  import path35 from "path";
19234
19333
  import fg4 from "fast-glob";
19235
19334
  function readLines2(filePath) {
19236
- return fs24.readFileSync(filePath, "utf-8").split("\n");
19335
+ return fs25.readFileSync(filePath, "utf-8").split("\n");
19237
19336
  }
19238
19337
  function writeLines(filePath, lines) {
19239
- fs24.writeFileSync(filePath, lines.join("\n"), "utf-8");
19338
+ fs25.writeFileSync(filePath, lines.join("\n"), "utf-8");
19240
19339
  }
19241
19340
  function getImportingFiles(store, fileId, projectRoot) {
19242
19341
  const fileNodeId = store.getNodeId("file", fileId);
@@ -19306,7 +19405,7 @@ function applyRename(store, projectRoot, symbolId, newName) {
19306
19405
  const regex = buildRenameRegex(oldName);
19307
19406
  const modifiedFiles = /* @__PURE__ */ new Set();
19308
19407
  for (const { filePath } of allFiles) {
19309
- if (!fs24.existsSync(filePath)) {
19408
+ if (!fs25.existsSync(filePath)) {
19310
19409
  result.warnings.push(`File not found on disk: ${filePath}`);
19311
19410
  continue;
19312
19411
  }
@@ -19387,7 +19486,7 @@ function removeDeadCode(store, projectRoot, symbolId) {
19387
19486
  return result;
19388
19487
  }
19389
19488
  const filePath = path35.resolve(projectRoot, symbolFile.path);
19390
- if (!fs24.existsSync(filePath)) {
19489
+ if (!fs25.existsSync(filePath)) {
19391
19490
  result.error = `File not found on disk: ${filePath}`;
19392
19491
  return result;
19393
19492
  }
@@ -19454,7 +19553,7 @@ function extractFunction(store, projectRoot, filePath, startLine, endLine, funct
19454
19553
  warnings: []
19455
19554
  };
19456
19555
  const absPath = path35.resolve(projectRoot, filePath);
19457
- if (!fs24.existsSync(absPath)) {
19556
+ if (!fs25.existsSync(absPath)) {
19458
19557
  result.error = `File not found: ${filePath}`;
19459
19558
  return result;
19460
19559
  }
@@ -19649,10 +19748,10 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
19649
19748
  const filesWithMatches = /* @__PURE__ */ new Set();
19650
19749
  for (const relPath of files) {
19651
19750
  const absPath = path35.resolve(projectRoot, relPath);
19652
- if (!fs24.existsSync(absPath)) continue;
19751
+ if (!fs25.existsSync(absPath)) continue;
19653
19752
  let content;
19654
19753
  try {
19655
- content = fs24.readFileSync(absPath, "utf-8");
19754
+ content = fs25.readFileSync(absPath, "utf-8");
19656
19755
  } catch {
19657
19756
  result.warnings.push(`Could not read: ${relPath}`);
19658
19757
  continue;
@@ -19736,12 +19835,12 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
19736
19835
  for (const relPath of filesWithMatches) {
19737
19836
  const absPath = path35.resolve(projectRoot, relPath);
19738
19837
  try {
19739
- const content = fs24.readFileSync(absPath, "utf-8");
19838
+ const content = fs25.readFileSync(absPath, "utf-8");
19740
19839
  const flags = options.multiline ? "gms" : "gm";
19741
19840
  const freshRegex = new RegExp(pattern, flags);
19742
19841
  const newContent = content.replace(freshRegex, replacement);
19743
19842
  if (newContent !== content) {
19744
- fs24.writeFileSync(absPath, newContent, "utf-8");
19843
+ fs25.writeFileSync(absPath, newContent, "utf-8");
19745
19844
  result.files_modified.push(relPath);
19746
19845
  }
19747
19846
  } catch (e) {
@@ -20472,7 +20571,7 @@ var TopologyStore = class {
20472
20571
  };
20473
20572
 
20474
20573
  // src/topology/service-detector.ts
20475
- import fs25 from "fs";
20574
+ import fs26 from "fs";
20476
20575
  import path36 from "path";
20477
20576
  function detectServices(repoRoots) {
20478
20577
  const services = [];
@@ -20497,14 +20596,14 @@ function detectFromDockerCompose(root) {
20497
20596
  let composePath;
20498
20597
  for (const f of composeFiles) {
20499
20598
  const p5 = path36.join(root, f);
20500
- if (fs25.existsSync(p5)) {
20599
+ if (fs26.existsSync(p5)) {
20501
20600
  composePath = p5;
20502
20601
  break;
20503
20602
  }
20504
20603
  }
20505
20604
  if (!composePath) return [];
20506
20605
  try {
20507
- const content = fs25.readFileSync(composePath, "utf-8");
20606
+ const content = fs26.readFileSync(composePath, "utf-8");
20508
20607
  const services = [];
20509
20608
  const lines = content.split("\n");
20510
20609
  let inServices = false;
@@ -20550,7 +20649,7 @@ function detectFromDockerCompose(root) {
20550
20649
  }
20551
20650
 
20552
20651
  // src/topology/contract-parser.ts
20553
- import fs26 from "fs";
20652
+ import fs27 from "fs";
20554
20653
  import path37 from "path";
20555
20654
  var EXCLUDE_DIRS = ["node_modules", "vendor", ".git", "dist", "build", "__pycache__"];
20556
20655
  function parseContracts(repoRoot) {
@@ -20558,7 +20657,7 @@ function parseContracts(repoRoot) {
20558
20657
  const specFiles = findSpecFiles(repoRoot);
20559
20658
  for (const { filePath, type } of specFiles) {
20560
20659
  try {
20561
- const content = fs26.readFileSync(filePath, "utf-8");
20660
+ const content = fs27.readFileSync(filePath, "utf-8");
20562
20661
  const relPath = path37.relative(repoRoot, filePath);
20563
20662
  let contract = null;
20564
20663
  switch (type) {
@@ -20678,7 +20777,7 @@ function findSpecFiles(root) {
20678
20777
  if (depth > 5) return;
20679
20778
  let entries;
20680
20779
  try {
20681
- entries = fs26.readdirSync(dir, { withFileTypes: true });
20780
+ entries = fs27.readdirSync(dir, { withFileTypes: true });
20682
20781
  } catch {
20683
20782
  return;
20684
20783
  }
@@ -20929,11 +21028,11 @@ function getContractDrift(topoStore, store, projectRoot, additionalRepos, opts)
20929
21028
 
20930
21029
  // src/federation/manager.ts
20931
21030
  import path39 from "path";
20932
- import fs28 from "fs";
21031
+ import fs29 from "fs";
20933
21032
  import Database3 from "better-sqlite3";
20934
21033
 
20935
21034
  // src/federation/scanner.ts
20936
- import fs27 from "fs";
21035
+ import fs28 from "fs";
20937
21036
  import path38 from "path";
20938
21037
  var CALL_PATTERNS2 = [
20939
21038
  // fetch('url') / fetch(`url`)
@@ -21061,7 +21160,7 @@ function walkAndScan(dir, repoRoot, results, depth) {
21061
21160
  if (depth > 10) return;
21062
21161
  let entries;
21063
21162
  try {
21064
- entries = fs27.readdirSync(dir, { withFileTypes: true });
21163
+ entries = fs28.readdirSync(dir, { withFileTypes: true });
21065
21164
  } catch {
21066
21165
  return;
21067
21166
  }
@@ -21072,7 +21171,7 @@ function walkAndScan(dir, repoRoot, results, depth) {
21072
21171
  walkAndScan(fullPath, repoRoot, results, depth + 1);
21073
21172
  } else if (entry.isFile() && CODE_EXTENSIONS.has(path38.extname(entry.name).toLowerCase())) {
21074
21173
  try {
21075
- const content = fs27.readFileSync(fullPath, "utf-8");
21174
+ const content = fs28.readFileSync(fullPath, "utf-8");
21076
21175
  const relPath = path38.relative(repoRoot, fullPath);
21077
21176
  scanFileContent(relPath, content, results);
21078
21177
  } catch {
@@ -21121,7 +21220,7 @@ var FederationManager = class {
21121
21220
  */
21122
21221
  add(repoRoot, opts) {
21123
21222
  const absRoot = path39.resolve(repoRoot);
21124
- if (!fs28.existsSync(absRoot)) {
21223
+ if (!fs29.existsSync(absRoot)) {
21125
21224
  throw new Error(`Repository path does not exist: ${absRoot}`);
21126
21225
  }
21127
21226
  const repoName = opts?.name ?? path39.basename(absRoot);
@@ -21129,7 +21228,7 @@ var FederationManager = class {
21129
21228
  const repoId = this.topoStore.upsertFederatedRepo({
21130
21229
  name: repoName,
21131
21230
  repoRoot: absRoot,
21132
- dbPath: fs28.existsSync(dbPath) ? dbPath : void 0,
21231
+ dbPath: fs29.existsSync(dbPath) ? dbPath : void 0,
21133
21232
  contractPaths: opts?.contractPaths
21134
21233
  });
21135
21234
  const detected = detectServices([absRoot]);
@@ -21146,7 +21245,7 @@ var FederationManager = class {
21146
21245
  if (opts?.contractPaths) {
21147
21246
  for (const cp of opts.contractPaths) {
21148
21247
  const absContract = path39.resolve(absRoot, cp);
21149
- if (fs28.existsSync(absContract)) {
21248
+ if (fs29.existsSync(absContract)) {
21150
21249
  const additionalContracts = parseContracts(path39.dirname(absContract));
21151
21250
  contracts.push(...additionalContracts.filter(
21152
21251
  (c) => path39.resolve(absRoot, c.specPath) === absContract
@@ -21295,7 +21394,7 @@ var FederationManager = class {
21295
21394
  let endpointsUpdated = 0;
21296
21395
  let clientCallsScanned = 0;
21297
21396
  for (const repo of repos) {
21298
- if (!fs28.existsSync(repo.repo_root)) {
21397
+ if (!fs29.existsSync(repo.repo_root)) {
21299
21398
  logger.warn({ repo: repo.name, root: repo.repo_root }, "Federated repo no longer exists, skipping");
21300
21399
  continue;
21301
21400
  }
@@ -21408,7 +21507,7 @@ var FederationManager = class {
21408
21507
  for (const [repoName, calls] of byRepo) {
21409
21508
  const repo2 = this.topoStore.getFederatedRepo(repoName);
21410
21509
  for (const call of calls) {
21411
- const symbols = repo2?.db_path && fs28.existsSync(repo2.db_path) ? resolveSymbolsAtLocation(repo2.db_path, call.file_path, call.line) : [];
21510
+ const symbols = repo2?.db_path && fs29.existsSync(repo2.db_path) ? resolveSymbolsAtLocation(repo2.db_path, call.file_path, call.line) : [];
21412
21511
  clients.push({
21413
21512
  repo: repoName,
21414
21513
  filePath: call.file_path,
@@ -23372,7 +23471,7 @@ function graphQuery(store, query, options = {}) {
23372
23471
  }
23373
23472
 
23374
23473
  // src/tools/analysis/dataflow.ts
23375
- import fs29 from "fs";
23474
+ import fs30 from "fs";
23376
23475
  import path40 from "path";
23377
23476
  function getDataflow(store, projectRoot, opts) {
23378
23477
  const symbol = opts.symbolId ? store.getSymbolBySymbolId(opts.symbolId) : opts.fqn ? store.getSymbolByFqn(opts.fqn) : void 0;
@@ -23387,7 +23486,7 @@ function getDataflow(store, projectRoot, opts) {
23387
23486
  const absPath = path40.resolve(projectRoot, file.path);
23388
23487
  let content;
23389
23488
  try {
23390
- content = fs29.readFileSync(absPath, "utf-8");
23489
+ content = fs30.readFileSync(absPath, "utf-8");
23391
23490
  } catch {
23392
23491
  return err(validationError(`Cannot read file: ${file.path}`));
23393
23492
  }
@@ -23540,7 +23639,7 @@ function escapeRegex3(str2) {
23540
23639
  }
23541
23640
 
23542
23641
  // src/tools/analysis/visualize.ts
23543
- import fs30 from "fs";
23642
+ import fs31 from "fs";
23544
23643
  import path41 from "path";
23545
23644
  var import_picomatch2 = __toESM(require_picomatch2(), 1);
23546
23645
  function detectCommunities(nodeIds, edges) {
@@ -23914,7 +24013,7 @@ function visualizeGraph(store, opts) {
23914
24013
  const layout = opts.layout ?? "force";
23915
24014
  const html = generateHtml(nodes, edges, communities, layout);
23916
24015
  const outputPath = opts.output ?? path41.join(process.env.TMPDIR ?? "/tmp", "trace-mcp-graph.html");
23917
- fs30.writeFileSync(outputPath, html, "utf-8");
24016
+ fs31.writeFileSync(outputPath, html, "utf-8");
23918
24017
  return ok({
23919
24018
  outputPath,
23920
24019
  nodes: nodes.length,
@@ -25819,7 +25918,7 @@ function getCommunityDetail(store, communityId) {
25819
25918
  }
25820
25919
 
25821
25920
  // src/tools/quality/audit-config.ts
25822
- import fs31 from "fs";
25921
+ import fs32 from "fs";
25823
25922
  import path42 from "path";
25824
25923
  var CONFIG_PATTERNS = [
25825
25924
  "CLAUDE.md",
@@ -25848,9 +25947,9 @@ function auditConfig(store, projectRoot, options = {}) {
25848
25947
  const fileContents = /* @__PURE__ */ new Map();
25849
25948
  for (const file of configFiles) {
25850
25949
  const absPath = resolveConfigPath(file, projectRoot);
25851
- if (!fs31.existsSync(absPath)) continue;
25950
+ if (!fs32.existsSync(absPath)) continue;
25852
25951
  try {
25853
- const content = fs31.readFileSync(absPath, "utf-8");
25952
+ const content = fs32.readFileSync(absPath, "utf-8");
25854
25953
  fileContents.set(file, { content, lines: content.split("\n") });
25855
25954
  totalTokens += Math.ceil(content.length / 4);
25856
25955
  } catch {
@@ -25863,7 +25962,7 @@ function auditConfig(store, projectRoot, options = {}) {
25863
25962
  if (pathMatches) {
25864
25963
  for (const ref of pathMatches) {
25865
25964
  const refPath = path42.join(projectRoot, ref);
25866
- if (!fs31.existsSync(refPath) && !store.getFile(ref)) {
25965
+ if (!fs32.existsSync(refPath) && !store.getFile(ref)) {
25867
25966
  issues.push({
25868
25967
  file,
25869
25968
  line: i + 1,
@@ -25976,11 +26075,11 @@ function findConfigFiles(projectRoot) {
25976
26075
  const found = [];
25977
26076
  for (const pattern of CONFIG_PATTERNS) {
25978
26077
  const absPath = path42.join(projectRoot, pattern);
25979
- if (fs31.existsSync(absPath)) found.push(pattern);
26078
+ if (fs32.existsSync(absPath)) found.push(pattern);
25980
26079
  }
25981
26080
  for (const pattern of GLOBAL_CONFIG_PATTERNS) {
25982
26081
  const absPath = pattern.replace("~", process.env.HOME ?? "");
25983
- if (fs31.existsSync(absPath)) found.push(pattern);
26082
+ if (fs32.existsSync(absPath)) found.push(pattern);
25984
26083
  }
25985
26084
  return found;
25986
26085
  }
@@ -26212,7 +26311,7 @@ function cfgToAscii(cfg) {
26212
26311
  }
26213
26312
 
26214
26313
  // src/tools/analysis/control-flow.ts
26215
- import fs32 from "fs";
26314
+ import fs33 from "fs";
26216
26315
  import path43 from "path";
26217
26316
  function getControlFlow(store, projectRoot, options) {
26218
26317
  const { symbolId, fqn, format, simplify } = options;
@@ -26237,10 +26336,10 @@ function getControlFlow(store, projectRoot, options) {
26237
26336
  return err(notFound(`file for symbol`));
26238
26337
  }
26239
26338
  const absPath = path43.isAbsolute(file.path) ? file.path : path43.join(projectRoot, file.path);
26240
- if (!fs32.existsSync(absPath)) {
26339
+ if (!fs33.existsSync(absPath)) {
26241
26340
  return err(validationError(`File not on disk: ${file.path}`));
26242
26341
  }
26243
- const content = fs32.readFileSync(absPath, "utf-8");
26342
+ const content = fs33.readFileSync(absPath, "utf-8");
26244
26343
  const lines = content.split("\n");
26245
26344
  const startLine = symbol.line_start ?? 1;
26246
26345
  const endLine = symbol.line_end ?? lines.length;
@@ -26301,12 +26400,12 @@ function simplifyCFG(cfg) {
26301
26400
  }
26302
26401
 
26303
26402
  // src/tools/project/package-deps.ts
26304
- import fs33 from "fs";
26403
+ import fs34 from "fs";
26305
26404
  import path44 from "path";
26306
26405
  function loadRegistry() {
26307
- if (!fs33.existsSync(REGISTRY_PATH)) return {};
26406
+ if (!fs34.existsSync(REGISTRY_PATH)) return {};
26308
26407
  try {
26309
- const raw = JSON.parse(fs33.readFileSync(REGISTRY_PATH, "utf-8"));
26408
+ const raw = JSON.parse(fs34.readFileSync(REGISTRY_PATH, "utf-8"));
26310
26409
  return raw.projects ?? raw ?? {};
26311
26410
  } catch {
26312
26411
  return {};
@@ -26315,9 +26414,9 @@ function loadRegistry() {
26315
26414
  function readManifest(repoPath) {
26316
26415
  const result = { name: void 0, deps: /* @__PURE__ */ new Map(), publishes: [] };
26317
26416
  const pkgJsonPath = path44.join(repoPath, "package.json");
26318
- if (fs33.existsSync(pkgJsonPath)) {
26417
+ if (fs34.existsSync(pkgJsonPath)) {
26319
26418
  try {
26320
- const pkg = JSON.parse(fs33.readFileSync(pkgJsonPath, "utf-8"));
26419
+ const pkg = JSON.parse(fs34.readFileSync(pkgJsonPath, "utf-8"));
26321
26420
  result.name = pkg.name;
26322
26421
  if (pkg.name) result.publishes.push(pkg.name);
26323
26422
  for (const [dep, ver] of Object.entries(pkg.dependencies ?? {})) {
@@ -26330,9 +26429,9 @@ function readManifest(repoPath) {
26330
26429
  }
26331
26430
  }
26332
26431
  const composerPath = path44.join(repoPath, "composer.json");
26333
- if (fs33.existsSync(composerPath)) {
26432
+ if (fs34.existsSync(composerPath)) {
26334
26433
  try {
26335
- const composer = JSON.parse(fs33.readFileSync(composerPath, "utf-8"));
26434
+ const composer = JSON.parse(fs34.readFileSync(composerPath, "utf-8"));
26336
26435
  if (composer.name) {
26337
26436
  result.name ??= composer.name;
26338
26437
  result.publishes.push(composer.name);
@@ -26348,9 +26447,9 @@ function readManifest(repoPath) {
26348
26447
  }
26349
26448
  }
26350
26449
  const pyprojectPath = path44.join(repoPath, "pyproject.toml");
26351
- if (fs33.existsSync(pyprojectPath)) {
26450
+ if (fs34.existsSync(pyprojectPath)) {
26352
26451
  try {
26353
- const content = fs33.readFileSync(pyprojectPath, "utf-8");
26452
+ const content = fs34.readFileSync(pyprojectPath, "utf-8");
26354
26453
  const nameMatch = content.match(/^name\s*=\s*"([^"]+)"/m);
26355
26454
  if (nameMatch) {
26356
26455
  result.name ??= nameMatch[1];
@@ -26375,7 +26474,7 @@ function getPackageDeps(options) {
26375
26474
  const publishMap = /* @__PURE__ */ new Map();
26376
26475
  for (const [repoPath, entry] of Object.entries(registry)) {
26377
26476
  const absPath = repoPath;
26378
- if (!fs33.existsSync(absPath)) continue;
26477
+ if (!fs34.existsSync(absPath)) continue;
26379
26478
  const manifest = readManifest(absPath);
26380
26479
  repoManifests.set(repoPath, manifest);
26381
26480
  const allPublishes = [...entry.publishes ?? [], ...manifest.publishes];
@@ -26729,7 +26828,7 @@ function escapeHtml(s) {
26729
26828
 
26730
26829
  // src/tools/refactoring/pack-context.ts
26731
26830
  init_graph_analysis();
26732
- import fs34 from "fs";
26831
+ import fs35 from "fs";
26733
26832
  import path45 from "path";
26734
26833
  function estimateTokens2(text) {
26735
26834
  return Math.ceil(text.length / 4);
@@ -26808,10 +26907,10 @@ ${outlineLines.join("\n")}
26808
26907
  let sourceTokens = 0;
26809
26908
  for (const f of files) {
26810
26909
  const absPath = path45.join(projectRoot, f.path);
26811
- if (!fs34.existsSync(absPath)) continue;
26910
+ if (!fs35.existsSync(absPath)) continue;
26812
26911
  let content;
26813
26912
  try {
26814
- content = fs34.readFileSync(absPath, "utf-8");
26913
+ content = fs35.readFileSync(absPath, "utf-8");
26815
26914
  } catch {
26816
26915
  continue;
26817
26916
  }
@@ -27728,11 +27827,11 @@ function registerAITools(server, ctx) {
27728
27827
  // src/bundles.ts
27729
27828
  import Database4 from "better-sqlite3";
27730
27829
  import path47 from "path";
27731
- import fs35 from "fs";
27830
+ import fs36 from "fs";
27732
27831
  import crypto5 from "crypto";
27733
27832
  var BUNDLES_DIR = path47.join(TRACE_MCP_HOME, "bundles");
27734
27833
  function ensureBundlesDir() {
27735
- fs35.mkdirSync(BUNDLES_DIR, { recursive: true });
27834
+ fs36.mkdirSync(BUNDLES_DIR, { recursive: true });
27736
27835
  }
27737
27836
  function getBundlePath(packageName, version) {
27738
27837
  const safeName = packageName.replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -27743,22 +27842,22 @@ function getManifestPath() {
27743
27842
  }
27744
27843
  function loadManifest() {
27745
27844
  const p5 = getManifestPath();
27746
- if (!fs35.existsSync(p5)) return { bundles: [] };
27845
+ if (!fs36.existsSync(p5)) return { bundles: [] };
27747
27846
  try {
27748
- return JSON.parse(fs35.readFileSync(p5, "utf-8"));
27847
+ return JSON.parse(fs36.readFileSync(p5, "utf-8"));
27749
27848
  } catch {
27750
27849
  return { bundles: [] };
27751
27850
  }
27752
27851
  }
27753
27852
  function saveManifest(manifest) {
27754
27853
  ensureBundlesDir();
27755
- fs35.writeFileSync(getManifestPath(), JSON.stringify(manifest, null, 2) + "\n");
27854
+ fs36.writeFileSync(getManifestPath(), JSON.stringify(manifest, null, 2) + "\n");
27756
27855
  }
27757
27856
  function exportBundle(sourceDbPath, packageName, version) {
27758
27857
  ensureBundlesDir();
27759
27858
  const bundlePath = getBundlePath(packageName, version);
27760
27859
  const src = new Database4(sourceDbPath, { readonly: true });
27761
- if (fs35.existsSync(bundlePath)) fs35.unlinkSync(bundlePath);
27860
+ if (fs36.existsSync(bundlePath)) fs36.unlinkSync(bundlePath);
27762
27861
  const dst = new Database4(bundlePath);
27763
27862
  dst.pragma("journal_mode = WAL");
27764
27863
  dst.pragma("synchronous = OFF");
@@ -27897,7 +27996,7 @@ function exportBundle(sourceDbPath, packageName, version) {
27897
27996
  dst.exec("VACUUM");
27898
27997
  dst.close();
27899
27998
  src.close();
27900
- const bundleContent = fs35.readFileSync(bundlePath);
27999
+ const bundleContent = fs36.readFileSync(bundlePath);
27901
28000
  const sha256 = crypto5.createHash("sha256").update(bundleContent).digest("hex");
27902
28001
  const sizeBytes = bundleContent.length;
27903
28002
  const entry = {
@@ -27929,7 +28028,7 @@ function removeBundle(packageName, version) {
27929
28028
  );
27930
28029
  for (const entry of toRemove) {
27931
28030
  const fp = path47.join(BUNDLES_DIR, entry.file);
27932
- if (fs35.existsSync(fp)) fs35.unlinkSync(fp);
28031
+ if (fs36.existsSync(fp)) fs36.unlinkSync(fp);
27933
28032
  }
27934
28033
  manifest.bundles = manifest.bundles.filter(
27935
28034
  (b) => !(b.package === packageName && (!version || b.version === version))
@@ -27939,7 +28038,7 @@ function removeBundle(packageName, version) {
27939
28038
  }
27940
28039
  function loadBundle(packageName, version) {
27941
28040
  const bundlePath = getBundlePath(packageName, version);
27942
- if (!fs35.existsSync(bundlePath)) return null;
28041
+ if (!fs36.existsSync(bundlePath)) return null;
27943
28042
  try {
27944
28043
  const db = new Database4(bundlePath, { readonly: true });
27945
28044
  return { package: packageName, version, db };
@@ -28225,7 +28324,7 @@ var AnalyticsStore = class {
28225
28324
  };
28226
28325
 
28227
28326
  // src/analytics/log-parser.ts
28228
- import fs36 from "fs";
28327
+ import fs37 from "fs";
28229
28328
  import path49 from "path";
28230
28329
  import os4 from "os";
28231
28330
  var CLAUDE_PROJECTS_DIR = path49.join(os4.homedir(), ".claude", "projects");
@@ -28303,7 +28402,7 @@ function processToolResult(item, toolResults) {
28303
28402
  }
28304
28403
  function parseSessionFile(filePath, projectPath) {
28305
28404
  try {
28306
- const content = fs36.readFileSync(filePath, "utf-8");
28405
+ const content = fs37.readFileSync(filePath, "utf-8");
28307
28406
  const lines = content.split("\n").filter((l) => l.trim());
28308
28407
  const sessionId = path49.basename(filePath, ".jsonl");
28309
28408
  const toolCalls = [];
@@ -28395,7 +28494,7 @@ function decodeDirName(dirName) {
28395
28494
  const seg = parts[i];
28396
28495
  const candidate = base + "/" + (tail ? tail + "-" + seg : seg);
28397
28496
  try {
28398
- if (fs36.statSync(candidate).isDirectory()) {
28497
+ if (fs37.statSync(candidate).isDirectory()) {
28399
28498
  base = candidate;
28400
28499
  tail = "";
28401
28500
  continue;
@@ -28405,7 +28504,7 @@ function decodeDirName(dirName) {
28405
28504
  if (tail) {
28406
28505
  const slashCandidate = base + "/" + tail;
28407
28506
  try {
28408
- if (fs36.statSync(slashCandidate).isDirectory()) {
28507
+ if (fs37.statSync(slashCandidate).isDirectory()) {
28409
28508
  base = slashCandidate;
28410
28509
  tail = seg;
28411
28510
  continue;
@@ -28418,8 +28517,8 @@ function decodeDirName(dirName) {
28418
28517
  return tail ? base + "/" + tail : base;
28419
28518
  }
28420
28519
  function listProjectDirs() {
28421
- if (!fs36.existsSync(CLAUDE_PROJECTS_DIR)) return [];
28422
- const entries = fs36.readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true });
28520
+ if (!fs37.existsSync(CLAUDE_PROJECTS_DIR)) return [];
28521
+ const entries = fs37.readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true });
28423
28522
  return entries.filter((e) => e.isDirectory()).map((e) => ({
28424
28523
  dirName: e.name,
28425
28524
  projectPath: decodeDirName(e.name)
@@ -28427,11 +28526,11 @@ function listProjectDirs() {
28427
28526
  }
28428
28527
  function listSessionFiles(projectDirName) {
28429
28528
  const dir = path49.join(CLAUDE_PROJECTS_DIR, projectDirName);
28430
- if (!fs36.existsSync(dir)) return [];
28431
- const entries = fs36.readdirSync(dir, { withFileTypes: true });
28529
+ if (!fs37.existsSync(dir)) return [];
28530
+ const entries = fs37.readdirSync(dir, { withFileTypes: true });
28432
28531
  return entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
28433
28532
  const filePath = path49.join(dir, e.name);
28434
- const stat = fs36.statSync(filePath);
28533
+ const stat = fs37.statSync(filePath);
28435
28534
  return { filePath, mtime: stat.mtimeMs };
28436
28535
  });
28437
28536
  }
@@ -28445,14 +28544,14 @@ function listAllSessions() {
28445
28544
  const clawProjectPaths = discoverClawProjects();
28446
28545
  for (const projectPath of clawProjectPaths) {
28447
28546
  const sessionsDir = path49.join(projectPath, CLAW_SESSIONS_DIR_NAME);
28448
- if (!fs36.existsSync(sessionsDir)) continue;
28547
+ if (!fs37.existsSync(sessionsDir)) continue;
28449
28548
  try {
28450
- const entries = fs36.readdirSync(sessionsDir, { withFileTypes: true });
28549
+ const entries = fs37.readdirSync(sessionsDir, { withFileTypes: true });
28451
28550
  for (const e of entries) {
28452
28551
  if (!e.isFile() || !e.name.endsWith(".jsonl")) continue;
28453
28552
  const filePath = path49.join(sessionsDir, e.name);
28454
28553
  try {
28455
- const stat = fs36.statSync(filePath);
28554
+ const stat = fs37.statSync(filePath);
28456
28555
  results.push({ filePath, projectPath, client: "claw-code", mtime: stat.mtimeMs });
28457
28556
  } catch {
28458
28557
  }
@@ -28465,25 +28564,25 @@ function listAllSessions() {
28465
28564
  function discoverClawProjects() {
28466
28565
  const paths = /* @__PURE__ */ new Set();
28467
28566
  for (const { projectPath } of listProjectDirs()) {
28468
- if (fs36.existsSync(path49.join(projectPath, CLAW_SESSIONS_DIR_NAME))) {
28567
+ if (fs37.existsSync(path49.join(projectPath, CLAW_SESSIONS_DIR_NAME))) {
28469
28568
  paths.add(projectPath);
28470
28569
  }
28471
28570
  }
28472
28571
  const cwd = process.cwd();
28473
- if (fs36.existsSync(path49.join(cwd, CLAW_SESSIONS_DIR_NAME))) {
28572
+ if (fs37.existsSync(path49.join(cwd, CLAW_SESSIONS_DIR_NAME))) {
28474
28573
  paths.add(cwd);
28475
28574
  }
28476
28575
  const home = os4.homedir();
28477
28576
  const commonRoots = ["Projects", "projects", "dev", "workspace", "code", "PhpstormProjects", "WebstormProjects", "src"];
28478
28577
  for (const root of commonRoots) {
28479
28578
  const rootDir = path49.join(home, root);
28480
- if (!fs36.existsSync(rootDir)) continue;
28579
+ if (!fs37.existsSync(rootDir)) continue;
28481
28580
  try {
28482
- const entries = fs36.readdirSync(rootDir, { withFileTypes: true });
28581
+ const entries = fs37.readdirSync(rootDir, { withFileTypes: true });
28483
28582
  for (const e of entries) {
28484
28583
  if (!e.isDirectory()) continue;
28485
28584
  const projectDir = path49.join(rootDir, e.name);
28486
- if (fs36.existsSync(path49.join(projectDir, CLAW_SESSIONS_DIR_NAME))) {
28585
+ if (fs37.existsSync(path49.join(projectDir, CLAW_SESSIONS_DIR_NAME))) {
28487
28586
  paths.add(projectDir);
28488
28587
  }
28489
28588
  }
@@ -29053,8 +29152,9 @@ function benchmarkContextBundle(store, symbols, count, rand) {
29053
29152
  const group = sampled.slice(i * batchSize, (i + 1) * batchSize);
29054
29153
  const totalSourceBytes = group.reduce((s, sym) => s + (sym.source_bytes || Math.round(sym.file_byte_length * 0.08)), 0);
29055
29154
  const importOverhead = group.length * 200;
29056
- const bl = estimateTokens3(totalSourceBytes + importOverhead);
29057
- const tm = estimateTokens3(Math.round((totalSourceBytes + importOverhead) * 0.6));
29155
+ const perCallHintsOverhead = group.length * 120;
29156
+ const bl = estimateTokens3(totalSourceBytes + importOverhead) + perCallHintsOverhead;
29157
+ const tm = estimateTokens3(Math.round((totalSourceBytes + importOverhead) * 0.45));
29058
29158
  const names = group.map((g) => g.name).join(", ");
29059
29159
  details.push({ query: names, file: group[0].file_path, baseline_tokens: bl, trace_mcp_tokens: tm, reduction_pct: reductionPct(bl, tm) });
29060
29160
  }
@@ -29067,10 +29167,13 @@ function benchmarkBatchOverhead(symbols, files, count, rand) {
29067
29167
  const details = [];
29068
29168
  for (let i = 0; i < batches; i++) {
29069
29169
  const group = sampledSymbols.slice(i * batchSize, (i + 1) * batchSize);
29070
- const perCallOverhead = 150;
29170
+ const perCallFramingOverhead = 150;
29171
+ const perCallHintsOverhead = 120;
29172
+ const perCallMetadataOverhead = 40;
29173
+ const perCallOverhead = perCallFramingOverhead + perCallHintsOverhead + perCallMetadataOverhead;
29071
29174
  const contentTokens = group.reduce((s, sym) => s + estimateTokens3(sym.source_bytes || 200), 0);
29072
29175
  const bl = contentTokens + batchSize * perCallOverhead;
29073
- const tm = contentTokens + perCallOverhead;
29176
+ const tm = contentTokens + perCallFramingOverhead;
29074
29177
  const names = group.map((g) => g.name).join(", ");
29075
29178
  details.push({ query: names, file: group[0].file_path, baseline_tokens: bl, trace_mcp_tokens: tm, reduction_pct: reductionPct(bl, tm) });
29076
29179
  }
@@ -29183,7 +29286,7 @@ function formatBenchmarkMarkdown(result) {
29183
29286
  }
29184
29287
 
29185
29288
  // src/analytics/tech-detector.ts
29186
- import fs37 from "fs";
29289
+ import fs38 from "fs";
29187
29290
  import path50 from "path";
29188
29291
 
29189
29292
  // src/analytics/known-packages.ts
@@ -29355,7 +29458,7 @@ var KNOWN_PACKAGES = {
29355
29458
  // src/analytics/tech-detector.ts
29356
29459
  function parsePackageJson(filePath) {
29357
29460
  try {
29358
- const pkg = JSON.parse(fs37.readFileSync(filePath, "utf-8"));
29461
+ const pkg = JSON.parse(fs38.readFileSync(filePath, "utf-8"));
29359
29462
  const deps = [];
29360
29463
  for (const [name, version] of Object.entries(pkg.dependencies ?? {})) {
29361
29464
  deps.push({ name, version: String(version), isDev: false });
@@ -29370,7 +29473,7 @@ function parsePackageJson(filePath) {
29370
29473
  }
29371
29474
  function parseComposerJson(filePath) {
29372
29475
  try {
29373
- const pkg = JSON.parse(fs37.readFileSync(filePath, "utf-8"));
29476
+ const pkg = JSON.parse(fs38.readFileSync(filePath, "utf-8"));
29374
29477
  const deps = [];
29375
29478
  for (const [name, version] of Object.entries(pkg.require ?? {})) {
29376
29479
  if (name === "php" || name.startsWith("ext-")) continue;
@@ -29386,7 +29489,7 @@ function parseComposerJson(filePath) {
29386
29489
  }
29387
29490
  function parseRequirementsTxt(filePath) {
29388
29491
  try {
29389
- const content = fs37.readFileSync(filePath, "utf-8");
29492
+ const content = fs38.readFileSync(filePath, "utf-8");
29390
29493
  const deps = [];
29391
29494
  for (const line of content.split("\n")) {
29392
29495
  const trimmed = line.trim();
@@ -29403,7 +29506,7 @@ function parseRequirementsTxt(filePath) {
29403
29506
  }
29404
29507
  function parsePyprojectToml(filePath) {
29405
29508
  try {
29406
- const content = fs37.readFileSync(filePath, "utf-8");
29509
+ const content = fs38.readFileSync(filePath, "utf-8");
29407
29510
  const deps = [];
29408
29511
  const depSection = content.match(/\[project\][\s\S]*?dependencies\s*=\s*\[([\s\S]*?)\]/);
29409
29512
  if (depSection) {
@@ -29419,7 +29522,7 @@ function parsePyprojectToml(filePath) {
29419
29522
  }
29420
29523
  function parseGoMod(filePath) {
29421
29524
  try {
29422
- const content = fs37.readFileSync(filePath, "utf-8");
29525
+ const content = fs38.readFileSync(filePath, "utf-8");
29423
29526
  const deps = [];
29424
29527
  const requireBlock = content.match(/require\s*\(([\s\S]*?)\)/);
29425
29528
  if (requireBlock) {
@@ -29439,7 +29542,7 @@ function parseGoMod(filePath) {
29439
29542
  }
29440
29543
  function parseGemfile(filePath) {
29441
29544
  try {
29442
- const content = fs37.readFileSync(filePath, "utf-8");
29545
+ const content = fs38.readFileSync(filePath, "utf-8");
29443
29546
  const deps = [];
29444
29547
  for (const line of content.split("\n")) {
29445
29548
  const m = line.match(/gem\s+['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]*)['""])?/);
@@ -29467,7 +29570,7 @@ function detectCoverage(projectRoot, opts = {}) {
29467
29570
  const allDeps = [];
29468
29571
  for (const { file, parser } of MANIFEST_PARSERS) {
29469
29572
  const filePath = path50.join(projectRoot, file);
29470
- if (!fs37.existsSync(filePath)) continue;
29573
+ if (!fs38.existsSync(filePath)) continue;
29471
29574
  manifestsFound.push(file);
29472
29575
  const rawDeps = parser(filePath);
29473
29576
  for (const raw of rawDeps) {
@@ -30239,7 +30342,14 @@ function registerSessionTools(server, ctx) {
30239
30342
  const text = response.content?.[0]?.text;
30240
30343
  if (text) {
30241
30344
  try {
30242
- results.push({ tool: call.tool, result: JSON.parse(text) });
30345
+ const parsed = JSON.parse(text);
30346
+ if (parsed && typeof parsed === "object") {
30347
+ delete parsed._hints;
30348
+ delete parsed._optimization_hint;
30349
+ delete parsed._budget_warning;
30350
+ delete parsed._budget_level;
30351
+ }
30352
+ results.push({ tool: call.tool, result: parsed });
30243
30353
  } catch {
30244
30354
  results.push({ tool: call.tool, result: text });
30245
30355
  }
@@ -30257,7 +30367,7 @@ function registerSessionTools(server, ctx) {
30257
30367
  }
30258
30368
 
30259
30369
  // src/server/server.ts
30260
- var PKG_VERSION = true ? "1.7.0" : "0.0.0-dev";
30370
+ var PKG_VERSION = true ? "1.8.0" : "0.0.0-dev";
30261
30371
  function j2(value) {
30262
30372
  return JSON.stringify(value, (_key, val) => val === null || val === void 0 ? void 0 : val);
30263
30373
  }
@@ -39077,7 +39187,7 @@ var XmlLanguagePlugin = class {
39077
39187
  };
39078
39188
 
39079
39189
  // src/indexer/plugins/integration/orm/prisma/index.ts
39080
- import fs38 from "fs";
39190
+ import fs39 from "fs";
39081
39191
  import path51 from "path";
39082
39192
  import { ok as ok28 } from "neverthrow";
39083
39193
  var PrismaLanguagePlugin = class {
@@ -39115,7 +39225,7 @@ var PrismaPlugin = class {
39115
39225
  path51.join(ctx.rootPath, "prisma", "schema.prisma"),
39116
39226
  path51.join(ctx.rootPath, "schema.prisma")
39117
39227
  ];
39118
- return candidates.some((p5) => fs38.existsSync(p5));
39228
+ return candidates.some((p5) => fs39.existsSync(p5));
39119
39229
  } catch {
39120
39230
  return false;
39121
39231
  }
@@ -39240,7 +39350,7 @@ function parsePrismaSchema(source) {
39240
39350
  }
39241
39351
 
39242
39352
  // src/indexer/plugins/integration/api/graphql/index.ts
39243
- import fs39 from "fs";
39353
+ import fs40 from "fs";
39244
39354
  import { ok as ok29 } from "neverthrow";
39245
39355
  var GraphQLLanguagePlugin = class {
39246
39356
  manifest = {
@@ -39282,7 +39392,7 @@ var GraphQLPlugin = class {
39282
39392
  ];
39283
39393
  if (gqlDeps.some((d) => d in deps)) return true;
39284
39394
  try {
39285
- return fs39.readdirSync(ctx.rootPath).some((f) => f.endsWith(".graphql") || f.endsWith(".gql"));
39395
+ return fs40.readdirSync(ctx.rootPath).some((f) => f.endsWith(".graphql") || f.endsWith(".gql"));
39286
39396
  } catch {
39287
39397
  return false;
39288
39398
  }
@@ -42044,7 +42154,7 @@ function createAllLanguagePlugins() {
42044
42154
  }
42045
42155
 
42046
42156
  // src/indexer/plugins/integration/framework/laravel/index.ts
42047
- import fs40 from "fs";
42157
+ import fs41 from "fs";
42048
42158
  import path52 from "path";
42049
42159
  import { ok as ok34 } from "neverthrow";
42050
42160
 
@@ -43848,7 +43958,7 @@ var LaravelPlugin = class {
43848
43958
  } else {
43849
43959
  try {
43850
43960
  const composerPath = path52.join(ctx.rootPath, "composer.json");
43851
- const content = fs40.readFileSync(composerPath, "utf-8");
43961
+ const content = fs41.readFileSync(composerPath, "utf-8");
43852
43962
  const json = JSON.parse(content);
43853
43963
  deps = json.require;
43854
43964
  } catch {
@@ -44520,7 +44630,7 @@ var LaravelPlugin = class {
44520
44630
  };
44521
44631
 
44522
44632
  // src/indexer/plugins/integration/framework/django/index.ts
44523
- import fs41 from "fs";
44633
+ import fs42 from "fs";
44524
44634
  import path53 from "path";
44525
44635
  import { ok as ok35 } from "neverthrow";
44526
44636
 
@@ -45028,13 +45138,13 @@ var DjangoPlugin = class {
45028
45138
  return true;
45029
45139
  }
45030
45140
  try {
45031
- fs41.accessSync(path53.join(ctx.rootPath, "manage.py"), fs41.constants.F_OK);
45141
+ fs42.accessSync(path53.join(ctx.rootPath, "manage.py"), fs42.constants.F_OK);
45032
45142
  return true;
45033
45143
  } catch {
45034
45144
  }
45035
45145
  try {
45036
45146
  const pyprojectPath = path53.join(ctx.rootPath, "pyproject.toml");
45037
- const content = fs41.readFileSync(pyprojectPath, "utf-8");
45147
+ const content = fs42.readFileSync(pyprojectPath, "utf-8");
45038
45148
  if (/django/i.test(content) && /dependencies|requires/i.test(content)) {
45039
45149
  return true;
45040
45150
  }
@@ -45042,7 +45152,7 @@ var DjangoPlugin = class {
45042
45152
  }
45043
45153
  try {
45044
45154
  const reqPath = path53.join(ctx.rootPath, "requirements.txt");
45045
- const content = fs41.readFileSync(reqPath, "utf-8");
45155
+ const content = fs42.readFileSync(reqPath, "utf-8");
45046
45156
  if (/^django(?:==|>=|<=|~=|!=|\[|\s|$)/im.test(content)) {
45047
45157
  return true;
45048
45158
  }
@@ -45050,7 +45160,7 @@ var DjangoPlugin = class {
45050
45160
  }
45051
45161
  try {
45052
45162
  const setupPath = path53.join(ctx.rootPath, "setup.py");
45053
- const content = fs41.readFileSync(setupPath, "utf-8");
45163
+ const content = fs42.readFileSync(setupPath, "utf-8");
45054
45164
  if (/['"]django['"]/i.test(content)) {
45055
45165
  return true;
45056
45166
  }
@@ -45124,7 +45234,7 @@ var DjangoPlugin = class {
45124
45234
  if (file.language !== "python") continue;
45125
45235
  let source;
45126
45236
  try {
45127
- source = fs41.readFileSync(
45237
+ source = fs42.readFileSync(
45128
45238
  path53.resolve(ctx.rootPath, file.path),
45129
45239
  "utf-8"
45130
45240
  );
@@ -45785,7 +45895,7 @@ function normalizePath(path108) {
45785
45895
  }
45786
45896
 
45787
45897
  // src/indexer/plugins/integration/framework/express/index.ts
45788
- import fs42 from "fs";
45898
+ import fs43 from "fs";
45789
45899
  import path54 from "path";
45790
45900
  var ROUTE_RE = /(?:app|router)\s*\.\s*(get|post|put|delete|patch|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/g;
45791
45901
  var MIDDLEWARE_RE = /(?:app|router)\s*\.\s*use\s*\(\s*['"`]([^'"`]+)['"`]/g;
@@ -45857,7 +45967,7 @@ var ExpressPlugin = class {
45857
45967
  }
45858
45968
  try {
45859
45969
  const pkgPath = path54.join(ctx.rootPath, "package.json");
45860
- const content = fs42.readFileSync(pkgPath, "utf-8");
45970
+ const content = fs43.readFileSync(pkgPath, "utf-8");
45861
45971
  const pkg = JSON.parse(content);
45862
45972
  const deps = {
45863
45973
  ...pkg.dependencies,
@@ -45916,7 +46026,7 @@ var ExpressPlugin = class {
45916
46026
  };
45917
46027
 
45918
46028
  // src/indexer/plugins/integration/framework/fastapi/index.ts
45919
- import fs43 from "fs";
46029
+ import fs44 from "fs";
45920
46030
  import path55 from "path";
45921
46031
  import { ok as ok38, err as err25 } from "neverthrow";
45922
46032
  var HTTP_METHODS3 = /* @__PURE__ */ new Set(["get", "post", "put", "delete", "patch", "options", "head"]);
@@ -45929,14 +46039,14 @@ function hasPythonDep(ctx, pkg) {
45929
46039
  if (ctx.requirementsTxt?.includes(lowerPkg)) return true;
45930
46040
  try {
45931
46041
  const pyprojectPath = path55.join(ctx.rootPath, "pyproject.toml");
45932
- const content = fs43.readFileSync(pyprojectPath, "utf-8");
46042
+ const content = fs44.readFileSync(pyprojectPath, "utf-8");
45933
46043
  const re = new RegExp(`["']${escapeRegExp(pkg)}[>=<\\[!~\\s"']`, "i");
45934
46044
  if (re.test(content)) return true;
45935
46045
  } catch {
45936
46046
  }
45937
46047
  try {
45938
46048
  const reqPath = path55.join(ctx.rootPath, "requirements.txt");
45939
- const content = fs43.readFileSync(reqPath, "utf-8");
46049
+ const content = fs44.readFileSync(reqPath, "utf-8");
45940
46050
  const re = new RegExp(`^${escapeRegExp(pkg)}\\b`, "im");
45941
46051
  if (re.test(content)) return true;
45942
46052
  } catch {
@@ -46228,7 +46338,7 @@ var FastAPIPlugin = class {
46228
46338
  };
46229
46339
 
46230
46340
  // src/indexer/plugins/integration/framework/flask/index.ts
46231
- import fs44 from "fs";
46341
+ import fs45 from "fs";
46232
46342
  import path56 from "path";
46233
46343
  import { ok as ok39, err as err26 } from "neverthrow";
46234
46344
  var DEFAULT_METHODS = ["GET"];
@@ -46241,14 +46351,14 @@ function hasPythonDep2(ctx, pkg) {
46241
46351
  if (ctx.requirementsTxt?.includes(lowerPkg)) return true;
46242
46352
  try {
46243
46353
  const pyprojectPath = path56.join(ctx.rootPath, "pyproject.toml");
46244
- const content = fs44.readFileSync(pyprojectPath, "utf-8");
46354
+ const content = fs45.readFileSync(pyprojectPath, "utf-8");
46245
46355
  const re = new RegExp(`["']${escapeRegExp(pkg)}[>=<\\[!~\\s"']`, "i");
46246
46356
  if (re.test(content)) return true;
46247
46357
  } catch {
46248
46358
  }
46249
46359
  try {
46250
46360
  const reqPath = path56.join(ctx.rootPath, "requirements.txt");
46251
- const content = fs44.readFileSync(reqPath, "utf-8");
46361
+ const content = fs45.readFileSync(reqPath, "utf-8");
46252
46362
  const re = new RegExp(`^${escapeRegExp(pkg)}\\b`, "im");
46253
46363
  if (re.test(content)) return true;
46254
46364
  } catch {
@@ -46523,7 +46633,7 @@ var FlaskPlugin = class {
46523
46633
  };
46524
46634
 
46525
46635
  // src/indexer/plugins/integration/framework/hono/index.ts
46526
- import fs45 from "fs";
46636
+ import fs46 from "fs";
46527
46637
  import path57 from "path";
46528
46638
  var ROUTE_RE2 = /(?:app|router|hono)\s*\.\s*(get|post|put|delete|patch|head|options|all)\s*\(\s*['"`]([^'"`]+)['"`]/g;
46529
46639
  var ON_RE = /(?:app|router|hono)\s*\.\s*on\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*['"`]([^'"`]+)['"`]/g;
@@ -46595,7 +46705,7 @@ var HonoPlugin = class {
46595
46705
  }
46596
46706
  try {
46597
46707
  const pkgPath = path57.join(ctx.rootPath, "package.json");
46598
- const content = fs45.readFileSync(pkgPath, "utf-8");
46708
+ const content = fs46.readFileSync(pkgPath, "utf-8");
46599
46709
  const pkg = JSON.parse(content);
46600
46710
  const deps = {
46601
46711
  ...pkg.dependencies,
@@ -46649,7 +46759,7 @@ var HonoPlugin = class {
46649
46759
  };
46650
46760
 
46651
46761
  // src/indexer/plugins/integration/framework/fastify/index.ts
46652
- import fs46 from "fs";
46762
+ import fs47 from "fs";
46653
46763
  import path58 from "path";
46654
46764
  var SHORTHAND_ROUTE_RE = /(?:fastify|app|server|instance)\s*\.\s*(get|post|put|delete|patch|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/g;
46655
46765
  var ROUTE_OBJECT_RE = /\.route\s*\(\s*\{[^}]*?method\s*:\s*['"`]([^'"`]+)['"`][^}]*?url\s*:\s*['"`]([^'"`]+)['"`]/g;
@@ -46710,7 +46820,7 @@ var FastifyPlugin = class {
46710
46820
  }
46711
46821
  try {
46712
46822
  const pkgPath = path58.join(ctx.rootPath, "package.json");
46713
- const content = fs46.readFileSync(pkgPath, "utf-8");
46823
+ const content = fs47.readFileSync(pkgPath, "utf-8");
46714
46824
  const pkg = JSON.parse(content);
46715
46825
  const deps = {
46716
46826
  ...pkg.dependencies,
@@ -46763,7 +46873,7 @@ var FastifyPlugin = class {
46763
46873
  };
46764
46874
 
46765
46875
  // src/indexer/plugins/integration/framework/nuxt/index.ts
46766
- import fs47 from "fs";
46876
+ import fs48 from "fs";
46767
46877
  import path59 from "path";
46768
46878
  function filePathToRoute(filePath, srcDir = ".") {
46769
46879
  const pagesPrefix = srcDir === "." ? "pages/" : `${srcDir}/pages/`;
@@ -46832,7 +46942,7 @@ var NuxtPlugin = class {
46832
46942
  }
46833
46943
  try {
46834
46944
  const configPath = path59.join(ctx.rootPath, "nuxt.config.ts");
46835
- const configContent = fs47.readFileSync(configPath, "utf-8");
46945
+ const configContent = fs48.readFileSync(configPath, "utf-8");
46836
46946
  if (/compatibilityVersion\s*:\s*4/.test(configContent)) {
46837
46947
  return true;
46838
46948
  }
@@ -46840,7 +46950,7 @@ var NuxtPlugin = class {
46840
46950
  }
46841
46951
  try {
46842
46952
  const appPagesDir = path59.join(ctx.rootPath, "app", "pages");
46843
- fs47.accessSync(appPagesDir);
46953
+ fs48.accessSync(appPagesDir);
46844
46954
  return true;
46845
46955
  } catch {
46846
46956
  }
@@ -46864,7 +46974,7 @@ var NuxtPlugin = class {
46864
46974
  }
46865
46975
  try {
46866
46976
  const configPath = path59.join(ctx.rootPath, "nuxt.config.ts");
46867
- fs47.accessSync(configPath);
46977
+ fs48.accessSync(configPath);
46868
46978
  this.nuxt4 = this.isNuxt4(ctx);
46869
46979
  this.srcDir = this.nuxt4 ? "app" : ".";
46870
46980
  return true;
@@ -46872,7 +46982,7 @@ var NuxtPlugin = class {
46872
46982
  }
46873
46983
  try {
46874
46984
  const pkgPath = path59.join(ctx.rootPath, "package.json");
46875
- const content = fs47.readFileSync(pkgPath, "utf-8");
46985
+ const content = fs48.readFileSync(pkgPath, "utf-8");
46876
46986
  const pkg = JSON.parse(content);
46877
46987
  const deps = {
46878
46988
  ...pkg.dependencies,
@@ -46973,7 +47083,7 @@ var NuxtPlugin = class {
46973
47083
  for (const file of vueFiles) {
46974
47084
  let source;
46975
47085
  try {
46976
- source = fs47.readFileSync(path59.resolve(ctx.rootPath, file.path), "utf-8");
47086
+ source = fs48.readFileSync(path59.resolve(ctx.rootPath, file.path), "utf-8");
46977
47087
  } catch {
46978
47088
  continue;
46979
47089
  }
@@ -47010,7 +47120,7 @@ var NuxtPlugin = class {
47010
47120
  };
47011
47121
 
47012
47122
  // src/indexer/plugins/integration/framework/nextjs/index.ts
47013
- import fs48 from "fs";
47123
+ import fs49 from "fs";
47014
47124
  import path60 from "path";
47015
47125
  var PAGE_EXTENSIONS = /\.(tsx|ts|jsx|js)$/;
47016
47126
  var APP_ROUTER_FILES = ["page", "layout", "loading", "error", "not-found", "route", "template", "default"];
@@ -47116,7 +47226,7 @@ var NextJSPlugin = class {
47116
47226
  }
47117
47227
  try {
47118
47228
  const pkgPath = path60.join(ctx.rootPath, "package.json");
47119
- const content = fs48.readFileSync(pkgPath, "utf-8");
47229
+ const content = fs49.readFileSync(pkgPath, "utf-8");
47120
47230
  const pkg = JSON.parse(content);
47121
47231
  const deps = {
47122
47232
  ...pkg.dependencies,
@@ -47341,7 +47451,7 @@ var NextJSPlugin = class {
47341
47451
  for (const file of pagesRouterFiles) {
47342
47452
  let source;
47343
47453
  try {
47344
- source = fs48.readFileSync(path60.resolve(ctx.rootPath, file.path), "utf-8");
47454
+ source = fs49.readFileSync(path60.resolve(ctx.rootPath, file.path), "utf-8");
47345
47455
  } catch {
47346
47456
  continue;
47347
47457
  }
@@ -47378,7 +47488,7 @@ var NextJSPlugin = class {
47378
47488
  };
47379
47489
 
47380
47490
  // src/indexer/plugins/integration/framework/gin/index.ts
47381
- import fs49 from "fs";
47491
+ import fs50 from "fs";
47382
47492
  import path61 from "path";
47383
47493
  var ROUTE_RE3 = /\b(\w+)\s*\.\s*(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|Any)\s*\(\s*"([^"]+)"/g;
47384
47494
  var GROUP_RE = /\b(\w+)\s*\.\s*Group\s*\(\s*"([^"]+)"/g;
@@ -47436,13 +47546,13 @@ var GinPlugin = class {
47436
47546
  detect(ctx) {
47437
47547
  try {
47438
47548
  const goModPath = path61.join(ctx.rootPath, "go.mod");
47439
- const content = fs49.readFileSync(goModPath, "utf-8");
47549
+ const content = fs50.readFileSync(goModPath, "utf-8");
47440
47550
  if (content.includes("github.com/gin-gonic/gin")) return true;
47441
47551
  } catch {
47442
47552
  }
47443
47553
  try {
47444
47554
  const goSumPath = path61.join(ctx.rootPath, "go.sum");
47445
- const content = fs49.readFileSync(goSumPath, "utf-8");
47555
+ const content = fs50.readFileSync(goSumPath, "utf-8");
47446
47556
  return content.includes("github.com/gin-gonic/gin");
47447
47557
  } catch {
47448
47558
  return false;
@@ -47503,7 +47613,7 @@ var GinPlugin = class {
47503
47613
  };
47504
47614
 
47505
47615
  // src/indexer/plugins/integration/framework/echo/index.ts
47506
- import fs50 from "fs";
47616
+ import fs51 from "fs";
47507
47617
  import path62 from "path";
47508
47618
  var ROUTE_RE4 = /\b(\w+)\s*\.\s*(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|CONNECT|TRACE)\s*\(\s*"([^"]+)"/g;
47509
47619
  var GROUP_RE2 = /\b(\w+)\s*\.\s*Group\s*\(\s*"([^"]+)"/g;
@@ -47561,13 +47671,13 @@ var EchoPlugin = class {
47561
47671
  detect(ctx) {
47562
47672
  try {
47563
47673
  const goModPath = path62.join(ctx.rootPath, "go.mod");
47564
- const content = fs50.readFileSync(goModPath, "utf-8");
47674
+ const content = fs51.readFileSync(goModPath, "utf-8");
47565
47675
  if (content.includes("github.com/labstack/echo")) return true;
47566
47676
  } catch {
47567
47677
  }
47568
47678
  try {
47569
47679
  const goSumPath = path62.join(ctx.rootPath, "go.sum");
47570
- const content = fs50.readFileSync(goSumPath, "utf-8");
47680
+ const content = fs51.readFileSync(goSumPath, "utf-8");
47571
47681
  return content.includes("github.com/labstack/echo");
47572
47682
  } catch {
47573
47683
  return false;
@@ -47734,7 +47844,7 @@ function extractTypeORMEntity(source, filePath) {
47734
47844
  }
47735
47845
 
47736
47846
  // src/indexer/plugins/integration/orm/sequelize/index.ts
47737
- import fs51 from "fs";
47847
+ import fs52 from "fs";
47738
47848
  import path63 from "path";
47739
47849
  import { ok as ok41 } from "neverthrow";
47740
47850
  var SequelizePlugin = class {
@@ -47753,7 +47863,7 @@ var SequelizePlugin = class {
47753
47863
  if ("sequelize" in deps || "sequelize-typescript" in deps) return true;
47754
47864
  try {
47755
47865
  const pkgPath = path63.join(ctx.rootPath, "package.json");
47756
- const content = fs51.readFileSync(pkgPath, "utf-8");
47866
+ const content = fs52.readFileSync(pkgPath, "utf-8");
47757
47867
  const json = JSON.parse(content);
47758
47868
  const allDeps = { ...json.dependencies, ...json.devDependencies };
47759
47869
  return "sequelize" in allDeps || "sequelize-typescript" in allDeps;
@@ -48073,7 +48183,7 @@ function extractScopes2(source, className) {
48073
48183
  }
48074
48184
 
48075
48185
  // src/indexer/plugins/integration/orm/mongoose/index.ts
48076
- import fs52 from "fs";
48186
+ import fs53 from "fs";
48077
48187
  import path64 from "path";
48078
48188
  import { ok as ok42 } from "neverthrow";
48079
48189
  var MongoosePlugin = class {
@@ -48092,7 +48202,7 @@ var MongoosePlugin = class {
48092
48202
  if ("mongoose" in deps) return true;
48093
48203
  try {
48094
48204
  const pkgPath = path64.join(ctx.rootPath, "package.json");
48095
- const content = fs52.readFileSync(pkgPath, "utf-8");
48205
+ const content = fs53.readFileSync(pkgPath, "utf-8");
48096
48206
  const json = JSON.parse(content);
48097
48207
  const allDeps = { ...json.dependencies, ...json.devDependencies };
48098
48208
  return "mongoose" in allDeps;
@@ -48381,7 +48491,7 @@ function extractRefs(fields, sourceModelName) {
48381
48491
  }
48382
48492
 
48383
48493
  // src/indexer/plugins/integration/orm/sqlalchemy/index.ts
48384
- import fs53 from "fs";
48494
+ import fs54 from "fs";
48385
48495
  import path65 from "path";
48386
48496
  import { ok as ok43, err as err27 } from "neverthrow";
48387
48497
  var MODEL_BASES = /* @__PURE__ */ new Set([
@@ -48400,14 +48510,14 @@ function hasPythonDep3(ctx, pkg) {
48400
48510
  if (ctx.requirementsTxt?.includes(lowerPkg)) return true;
48401
48511
  try {
48402
48512
  const pyprojectPath = path65.join(ctx.rootPath, "pyproject.toml");
48403
- const content = fs53.readFileSync(pyprojectPath, "utf-8");
48513
+ const content = fs54.readFileSync(pyprojectPath, "utf-8");
48404
48514
  const re = new RegExp(`["']${escapeRegExp(pkg)}[>=<\\[!~\\s"']`, "i");
48405
48515
  if (re.test(content)) return true;
48406
48516
  } catch {
48407
48517
  }
48408
48518
  try {
48409
48519
  const reqPath = path65.join(ctx.rootPath, "requirements.txt");
48410
- const content = fs53.readFileSync(reqPath, "utf-8");
48520
+ const content = fs54.readFileSync(reqPath, "utf-8");
48411
48521
  const re = new RegExp(`^${escapeRegExp(pkg)}\\b`, "im");
48412
48522
  if (re.test(content)) return true;
48413
48523
  } catch {
@@ -48962,7 +49072,7 @@ function toModelName(varName) {
48962
49072
  }
48963
49073
 
48964
49074
  // src/indexer/plugins/integration/orm/raw-sql/index.ts
48965
- import fs54 from "fs";
49075
+ import fs55 from "fs";
48966
49076
  import path66 from "path";
48967
49077
  var RAW_SQL_PACKAGES = [
48968
49078
  "better-sqlite3",
@@ -49043,7 +49153,7 @@ var RawSqlPlugin = class {
49043
49153
  }
49044
49154
  try {
49045
49155
  const pkgPath = path66.join(ctx.rootPath, "package.json");
49046
- const content = fs54.readFileSync(pkgPath, "utf-8");
49156
+ const content = fs55.readFileSync(pkgPath, "utf-8");
49047
49157
  const pkg = JSON.parse(content);
49048
49158
  const deps = {
49049
49159
  ...pkg.dependencies,
@@ -49319,7 +49429,7 @@ var ReactPlugin = class {
49319
49429
  };
49320
49430
 
49321
49431
  // src/indexer/plugins/integration/view/vue/index.ts
49322
- import fs55 from "fs";
49432
+ import fs56 from "fs";
49323
49433
  import path67 from "path";
49324
49434
 
49325
49435
  // src/indexer/plugins/integration/view/vue/resolver.ts
@@ -49360,7 +49470,7 @@ var VueFrameworkPlugin = class {
49360
49470
  }
49361
49471
  try {
49362
49472
  const pkgPath = path67.join(ctx.rootPath, "package.json");
49363
- const content = fs55.readFileSync(pkgPath, "utf-8");
49473
+ const content = fs56.readFileSync(pkgPath, "utf-8");
49364
49474
  const pkg = JSON.parse(content);
49365
49475
  const deps = {
49366
49476
  ...pkg.dependencies,
@@ -49464,7 +49574,7 @@ var VueFrameworkPlugin = class {
49464
49574
  };
49465
49575
 
49466
49576
  // src/indexer/plugins/integration/view/react-native/index.ts
49467
- import fs56 from "fs";
49577
+ import fs57 from "fs";
49468
49578
  import path68 from "path";
49469
49579
  import { ok as ok46 } from "neverthrow";
49470
49580
  function expoFileToRoute(filePath) {
@@ -49504,7 +49614,7 @@ var ReactNativePlugin = class {
49504
49614
  }
49505
49615
  try {
49506
49616
  const pkgPath = path68.join(ctx.rootPath, "package.json");
49507
- const content = fs56.readFileSync(pkgPath, "utf-8");
49617
+ const content = fs57.readFileSync(pkgPath, "utf-8");
49508
49618
  const json = JSON.parse(content);
49509
49619
  const allDeps = { ...json.dependencies, ...json.devDependencies };
49510
49620
  if ("expo-router" in allDeps) this.hasExpoRouter = true;
@@ -49810,7 +49920,7 @@ function extractNativeModuleNames(source) {
49810
49920
  }
49811
49921
 
49812
49922
  // src/indexer/plugins/integration/view/blade/index.ts
49813
- import fs57 from "fs";
49923
+ import fs58 from "fs";
49814
49924
  import path69 from "path";
49815
49925
  var EXTENDS_RE = /@extends\(\s*['"]([\w.-]+)['"]\s*\)/g;
49816
49926
  var INCLUDE_RE = /@include(?:If|When|Unless|First)?\(\s*['"]([\w.-]+)['"]/g;
@@ -49870,7 +49980,7 @@ var BladePlugin = class {
49870
49980
  detect(ctx) {
49871
49981
  try {
49872
49982
  const viewsDir = path69.join(ctx.rootPath, "resources", "views");
49873
- const stat = fs57.statSync(viewsDir);
49983
+ const stat = fs58.statSync(viewsDir);
49874
49984
  if (!stat.isDirectory()) return false;
49875
49985
  return this.hasBlade(viewsDir);
49876
49986
  } catch {
@@ -49952,7 +50062,7 @@ var BladePlugin = class {
49952
50062
  }
49953
50063
  hasBlade(dir) {
49954
50064
  try {
49955
- const entries = fs57.readdirSync(dir, { withFileTypes: true });
50065
+ const entries = fs58.readdirSync(dir, { withFileTypes: true });
49956
50066
  for (const entry of entries) {
49957
50067
  if (entry.isFile() && entry.name.endsWith(".blade.php")) return true;
49958
50068
  if (entry.isDirectory()) {
@@ -49966,7 +50076,7 @@ var BladePlugin = class {
49966
50076
  };
49967
50077
 
49968
50078
  // src/indexer/plugins/integration/view/inertia/index.ts
49969
- import fs58 from "fs";
50079
+ import fs59 from "fs";
49970
50080
  import path70 from "path";
49971
50081
  var INERTIA_RENDER_RE = /(?:Inertia::render|inertia)\(\s*['"]([\w/.-]+)['"]\s*(?:,\s*\[([^\]]*)\])?\s*\)/g;
49972
50082
  var ARRAY_KEY_RE = /['"](\w+)['"]\s*=>/g;
@@ -50014,7 +50124,7 @@ var InertiaPlugin = class {
50014
50124
  }
50015
50125
  try {
50016
50126
  const composerPath = path70.join(ctx.rootPath, "composer.json");
50017
- const content = fs58.readFileSync(composerPath, "utf-8");
50127
+ const content = fs59.readFileSync(composerPath, "utf-8");
50018
50128
  const json = JSON.parse(content);
50019
50129
  const req = json.require;
50020
50130
  if (req?.["inertiajs/inertia-laravel"]) return true;
@@ -50022,7 +50132,7 @@ var InertiaPlugin = class {
50022
50132
  }
50023
50133
  try {
50024
50134
  const pkgPath = path70.join(ctx.rootPath, "package.json");
50025
- const content = fs58.readFileSync(pkgPath, "utf-8");
50135
+ const content = fs59.readFileSync(pkgPath, "utf-8");
50026
50136
  const pkg = JSON.parse(content);
50027
50137
  const deps = {
50028
50138
  ...pkg.dependencies,
@@ -50063,7 +50173,7 @@ var InertiaPlugin = class {
50063
50173
  if (file.language !== "php") continue;
50064
50174
  let source;
50065
50175
  try {
50066
- source = fs58.readFileSync(path70.resolve(ctx.rootPath, file.path), "utf-8");
50176
+ source = fs59.readFileSync(path70.resolve(ctx.rootPath, file.path), "utf-8");
50067
50177
  } catch {
50068
50178
  continue;
50069
50179
  }
@@ -50114,7 +50224,7 @@ var InertiaPlugin = class {
50114
50224
  };
50115
50225
 
50116
50226
  // src/indexer/plugins/integration/view/shadcn/index.ts
50117
- import fs59 from "fs";
50227
+ import fs60 from "fs";
50118
50228
  import path71 from "path";
50119
50229
  import { ok as ok47 } from "neverthrow";
50120
50230
  var CVA_RE = /(?:export\s+(?:default\s+)?)?(?:const|let)\s+(\w+)\s*=\s*cva\s*\(/g;
@@ -50441,7 +50551,7 @@ function scanInstalledComponents(rootPath, config) {
50441
50551
  for (const relDir of possibleDirs) {
50442
50552
  const absDir = path71.resolve(rootPath, relDir);
50443
50553
  try {
50444
- const entries = fs59.readdirSync(absDir, { withFileTypes: true });
50554
+ const entries = fs60.readdirSync(absDir, { withFileTypes: true });
50445
50555
  for (const entry of entries) {
50446
50556
  if (entry.isFile() && /\.(tsx|vue|ts|jsx)$/.test(entry.name)) {
50447
50557
  const baseName = entry.name.replace(/\.(tsx|vue|ts|jsx)$/, "");
@@ -50452,7 +50562,7 @@ function scanInstalledComponents(rootPath, config) {
50452
50562
  });
50453
50563
  } else if (entry.isDirectory()) {
50454
50564
  try {
50455
- const subEntries = fs59.readdirSync(path71.join(absDir, entry.name));
50565
+ const subEntries = fs60.readdirSync(path71.join(absDir, entry.name));
50456
50566
  const indexFile = subEntries.find((f) => /^index\.(tsx|vue|ts|jsx)$/.test(f));
50457
50567
  if (indexFile) {
50458
50568
  components.push({
@@ -50501,7 +50611,7 @@ var ShadcnPlugin = class {
50501
50611
  this.rootPath = ctx.rootPath;
50502
50612
  try {
50503
50613
  const configPath = path71.join(ctx.rootPath, "components.json");
50504
- const raw = fs59.readFileSync(configPath, "utf-8");
50614
+ const raw = fs60.readFileSync(configPath, "utf-8");
50505
50615
  this.config = JSON.parse(raw);
50506
50616
  this.scanComponents(ctx);
50507
50617
  return true;
@@ -51377,7 +51487,7 @@ var HeadlessUiPlugin = class {
51377
51487
  };
51378
51488
 
51379
51489
  // src/indexer/plugins/integration/view/nuxt-ui/index.ts
51380
- import fs60 from "fs";
51490
+ import fs61 from "fs";
51381
51491
  import path72 from "path";
51382
51492
  import { ok as ok51 } from "neverthrow";
51383
51493
  var NUXT_UI_V3_COMPONENTS = /* @__PURE__ */ new Set([
@@ -51635,7 +51745,7 @@ var NuxtUiPlugin = class {
51635
51745
  if (!hasNuxtUi) {
51636
51746
  try {
51637
51747
  const configPath = path72.join(ctx.rootPath, "nuxt.config.ts");
51638
- const configContent = fs60.readFileSync(configPath, "utf-8");
51748
+ const configContent = fs61.readFileSync(configPath, "utf-8");
51639
51749
  if (/@nuxt\/ui/.test(configContent)) return true;
51640
51750
  } catch {
51641
51751
  }
@@ -51834,7 +51944,7 @@ function extractBraceBody4(source, pos) {
51834
51944
  }
51835
51945
 
51836
51946
  // src/indexer/plugins/integration/view/angular/index.ts
51837
- import fs61 from "fs";
51947
+ import fs62 from "fs";
51838
51948
  import path73 from "path";
51839
51949
  var COMPONENT_RE2 = /@Component\s*\(\s*\{[^}]*selector\s*:\s*['"]([^'"]+)['"]/gs;
51840
51950
  var INJECTABLE_RE2 = /@Injectable\s*\(/g;
@@ -51884,7 +51994,7 @@ var AngularPlugin = class {
51884
51994
  }
51885
51995
  try {
51886
51996
  const pkgPath = path73.join(ctx.rootPath, "package.json");
51887
- const content = fs61.readFileSync(pkgPath, "utf-8");
51997
+ const content = fs62.readFileSync(pkgPath, "utf-8");
51888
51998
  const pkg = JSON.parse(content);
51889
51999
  const deps = {
51890
52000
  ...pkg.dependencies,
@@ -52203,7 +52313,7 @@ function isHtmlTag(tag) {
52203
52313
  }
52204
52314
 
52205
52315
  // src/indexer/plugins/integration/view/svelte/index.ts
52206
- import fs62 from "fs";
52316
+ import fs63 from "fs";
52207
52317
  import path74 from "path";
52208
52318
  var EXPORT_LET_RE = /export\s+let\s+(\w+)/g;
52209
52319
  var SLOT_RE = /<slot(?:\s+name\s*=\s*['"]([^'"]+)['"])?\s*\/?>/g;
@@ -52266,7 +52376,7 @@ var SveltePlugin = class {
52266
52376
  }
52267
52377
  try {
52268
52378
  const pkgPath = path74.join(ctx.rootPath, "package.json");
52269
- const content = fs62.readFileSync(pkgPath, "utf-8");
52379
+ const content = fs63.readFileSync(pkgPath, "utf-8");
52270
52380
  const pkg = JSON.parse(content);
52271
52381
  const deps = {
52272
52382
  ...pkg.dependencies,
@@ -52513,7 +52623,7 @@ var SveltePlugin = class {
52513
52623
  };
52514
52624
 
52515
52625
  // src/indexer/plugins/integration/api/trpc/index.ts
52516
- import fs63 from "fs";
52626
+ import fs64 from "fs";
52517
52627
  import path75 from "path";
52518
52628
  var PROCEDURE_RE = /(\w+)\s*:\s*\w*[Pp]rocedure[\s\S]{0,500}?\.(query|mutation|subscription)\s*\(/g;
52519
52629
  var ROUTER_RE = /(?:t\.router|router)\s*\(\s*\{/g;
@@ -52547,7 +52657,7 @@ var TrpcPlugin = class {
52547
52657
  }
52548
52658
  try {
52549
52659
  const pkgPath = path75.join(ctx.rootPath, "package.json");
52550
- const content = fs63.readFileSync(pkgPath, "utf-8");
52660
+ const content = fs64.readFileSync(pkgPath, "utf-8");
52551
52661
  const pkg = JSON.parse(content);
52552
52662
  const deps = {
52553
52663
  ...pkg.dependencies,
@@ -52593,31 +52703,31 @@ var TrpcPlugin = class {
52593
52703
  };
52594
52704
 
52595
52705
  // src/indexer/plugins/integration/api/drf/index.ts
52596
- import fs64 from "fs";
52706
+ import fs65 from "fs";
52597
52707
  import path76 from "path";
52598
52708
  import { ok as ok52, err as err29 } from "neverthrow";
52599
52709
  function hasPythonDep4(rootPath, depName) {
52600
52710
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
52601
52711
  try {
52602
- const content = fs64.readFileSync(path76.join(rootPath, reqFile), "utf-8");
52712
+ const content = fs65.readFileSync(path76.join(rootPath, reqFile), "utf-8");
52603
52713
  if (new RegExp(`^${escapeRegExp(depName)}\\b`, "m").test(content)) return true;
52604
52714
  } catch {
52605
52715
  }
52606
52716
  }
52607
52717
  try {
52608
- const content = fs64.readFileSync(path76.join(rootPath, "pyproject.toml"), "utf-8");
52718
+ const content = fs65.readFileSync(path76.join(rootPath, "pyproject.toml"), "utf-8");
52609
52719
  if (content.includes(depName)) return true;
52610
52720
  } catch {
52611
52721
  }
52612
52722
  for (const f of ["setup.py", "setup.cfg"]) {
52613
52723
  try {
52614
- const content = fs64.readFileSync(path76.join(rootPath, f), "utf-8");
52724
+ const content = fs65.readFileSync(path76.join(rootPath, f), "utf-8");
52615
52725
  if (content.includes(depName)) return true;
52616
52726
  } catch {
52617
52727
  }
52618
52728
  }
52619
52729
  try {
52620
- const content = fs64.readFileSync(path76.join(rootPath, "Pipfile"), "utf-8");
52730
+ const content = fs65.readFileSync(path76.join(rootPath, "Pipfile"), "utf-8");
52621
52731
  if (content.includes(depName)) return true;
52622
52732
  } catch {
52623
52733
  }
@@ -52931,7 +53041,7 @@ var DRFPlugin = class {
52931
53041
  };
52932
53042
 
52933
53043
  // src/indexer/plugins/integration/api/mcp-sdk/index.ts
52934
- import fs65 from "fs";
53044
+ import fs66 from "fs";
52935
53045
  import path77 from "path";
52936
53046
  var MCP_SDK_PKG = "@modelcontextprotocol/sdk";
52937
53047
  var TOOL_RE = /\.tool\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]*)['"]\s*)?/g;
@@ -52974,7 +53084,7 @@ var McpSdkPlugin = class {
52974
53084
  }
52975
53085
  try {
52976
53086
  const pkgPath = path77.join(ctx.rootPath, "package.json");
52977
- const content = fs65.readFileSync(pkgPath, "utf-8");
53087
+ const content = fs66.readFileSync(pkgPath, "utf-8");
52978
53088
  const pkg = JSON.parse(content);
52979
53089
  const deps = {
52980
53090
  ...pkg.dependencies,
@@ -53025,7 +53135,7 @@ var McpSdkPlugin = class {
53025
53135
  };
53026
53136
 
53027
53137
  // src/indexer/plugins/integration/validation/zod/index.ts
53028
- import fs66 from "fs";
53138
+ import fs67 from "fs";
53029
53139
  import path78 from "path";
53030
53140
  var ZOD_OBJECT_RE = /(?:export\s+(?:default\s+)?)?(?:const|let|var)\s+(\w+)\s*=\s*z\.object\s*\(\s*\{([^]*?)\}\s*\)/g;
53031
53141
  var ZOD_FIELD_RE = /(\w+)\s*:\s*z\.(\w+)\s*\(([^)]*)\)([.\w()]*)/g;
@@ -53082,7 +53192,7 @@ var ZodPlugin = class {
53082
53192
  }
53083
53193
  try {
53084
53194
  const pkgPath = path78.join(ctx.rootPath, "package.json");
53085
- const content = fs66.readFileSync(pkgPath, "utf-8");
53195
+ const content = fs67.readFileSync(pkgPath, "utf-8");
53086
53196
  const pkg = JSON.parse(content);
53087
53197
  const deps = {
53088
53198
  ...pkg.dependencies,
@@ -53125,31 +53235,31 @@ var ZodPlugin = class {
53125
53235
  };
53126
53236
 
53127
53237
  // src/indexer/plugins/integration/validation/pydantic/index.ts
53128
- import fs67 from "fs";
53238
+ import fs68 from "fs";
53129
53239
  import path79 from "path";
53130
53240
  import { ok as ok53, err as err30 } from "neverthrow";
53131
53241
  function hasPythonDep5(rootPath, depName) {
53132
53242
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
53133
53243
  try {
53134
- const content = fs67.readFileSync(path79.join(rootPath, reqFile), "utf-8");
53244
+ const content = fs68.readFileSync(path79.join(rootPath, reqFile), "utf-8");
53135
53245
  if (new RegExp(`^${escapeRegExp(depName)}\\b`, "m").test(content)) return true;
53136
53246
  } catch {
53137
53247
  }
53138
53248
  }
53139
53249
  try {
53140
- const content = fs67.readFileSync(path79.join(rootPath, "pyproject.toml"), "utf-8");
53250
+ const content = fs68.readFileSync(path79.join(rootPath, "pyproject.toml"), "utf-8");
53141
53251
  if (content.includes(depName)) return true;
53142
53252
  } catch {
53143
53253
  }
53144
53254
  for (const f of ["setup.py", "setup.cfg"]) {
53145
53255
  try {
53146
- const content = fs67.readFileSync(path79.join(rootPath, f), "utf-8");
53256
+ const content = fs68.readFileSync(path79.join(rootPath, f), "utf-8");
53147
53257
  if (content.includes(depName)) return true;
53148
53258
  } catch {
53149
53259
  }
53150
53260
  }
53151
53261
  try {
53152
- const content = fs67.readFileSync(path79.join(rootPath, "Pipfile"), "utf-8");
53262
+ const content = fs68.readFileSync(path79.join(rootPath, "Pipfile"), "utf-8");
53153
53263
  if (content.includes(depName)) return true;
53154
53264
  } catch {
53155
53265
  }
@@ -53692,7 +53802,7 @@ function extractBraceBody5(source, pos) {
53692
53802
  }
53693
53803
 
53694
53804
  // src/indexer/plugins/integration/realtime/socketio/index.ts
53695
- import fs68 from "fs";
53805
+ import fs69 from "fs";
53696
53806
  import path80 from "path";
53697
53807
  var LISTENER_RE = /(?:socket|io|server|namespace)\s*\.\s*on\s*\(\s*['"`]([^'"`]+)['"`]/g;
53698
53808
  var EMITTER_RE = /(?:socket|io|server|namespace)(?:\.broadcast)?\s*\.\s*emit\s*\(\s*['"`]([^'"`]+)['"`]/g;
@@ -53737,7 +53847,7 @@ var SocketIoPlugin = class {
53737
53847
  }
53738
53848
  try {
53739
53849
  const pkgPath = path80.join(ctx.rootPath, "package.json");
53740
- const content = fs68.readFileSync(pkgPath, "utf-8");
53850
+ const content = fs69.readFileSync(pkgPath, "utf-8");
53741
53851
  const pkg = JSON.parse(content);
53742
53852
  const deps = {
53743
53853
  ...pkg.dependencies,
@@ -53791,7 +53901,7 @@ var SocketIoPlugin = class {
53791
53901
  };
53792
53902
 
53793
53903
  // src/indexer/plugins/integration/testing/index.ts
53794
- import fs69 from "fs";
53904
+ import fs70 from "fs";
53795
53905
 
53796
53906
  // src/utils/regex.ts
53797
53907
  var globalReCache = /* @__PURE__ */ new WeakMap();
@@ -53914,7 +54024,7 @@ var TestingPlugin = class {
53914
54024
  }
53915
54025
  try {
53916
54026
  const pkgPath = path81.join(ctx.rootPath, "package.json");
53917
- const content = fs69.readFileSync(pkgPath, "utf-8");
54027
+ const content = fs70.readFileSync(pkgPath, "utf-8");
53918
54028
  const pkg = JSON.parse(content);
53919
54029
  const deps = {
53920
54030
  ...pkg.dependencies,
@@ -53985,31 +54095,31 @@ var TestingPlugin = class {
53985
54095
  };
53986
54096
 
53987
54097
  // src/indexer/plugins/integration/tooling/celery/index.ts
53988
- import fs70 from "fs";
54098
+ import fs71 from "fs";
53989
54099
  import path82 from "path";
53990
54100
  import { ok as ok55, err as err31 } from "neverthrow";
53991
54101
  function hasPythonDep6(rootPath, depName) {
53992
54102
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
53993
54103
  try {
53994
- const content = fs70.readFileSync(path82.join(rootPath, reqFile), "utf-8");
54104
+ const content = fs71.readFileSync(path82.join(rootPath, reqFile), "utf-8");
53995
54105
  if (new RegExp(`^${escapeRegExp(depName)}\\b`, "m").test(content)) return true;
53996
54106
  } catch {
53997
54107
  }
53998
54108
  }
53999
54109
  try {
54000
- const content = fs70.readFileSync(path82.join(rootPath, "pyproject.toml"), "utf-8");
54110
+ const content = fs71.readFileSync(path82.join(rootPath, "pyproject.toml"), "utf-8");
54001
54111
  if (content.includes(depName)) return true;
54002
54112
  } catch {
54003
54113
  }
54004
54114
  for (const f of ["setup.py", "setup.cfg"]) {
54005
54115
  try {
54006
- const content = fs70.readFileSync(path82.join(rootPath, f), "utf-8");
54116
+ const content = fs71.readFileSync(path82.join(rootPath, f), "utf-8");
54007
54117
  if (content.includes(depName)) return true;
54008
54118
  } catch {
54009
54119
  }
54010
54120
  }
54011
54121
  try {
54012
- const content = fs70.readFileSync(path82.join(rootPath, "Pipfile"), "utf-8");
54122
+ const content = fs71.readFileSync(path82.join(rootPath, "Pipfile"), "utf-8");
54013
54123
  if (content.includes(depName)) return true;
54014
54124
  } catch {
54015
54125
  }
@@ -54257,7 +54367,7 @@ var CeleryPlugin = class {
54257
54367
  };
54258
54368
 
54259
54369
  // src/indexer/plugins/integration/tooling/n8n/index.ts
54260
- import fs71 from "fs";
54370
+ import fs72 from "fs";
54261
54371
  import path83 from "path";
54262
54372
  var CODE_TYPES = /* @__PURE__ */ new Set([
54263
54373
  "n8n-nodes-base.code",
@@ -54886,7 +54996,7 @@ function findDisconnectedNodes(workflow, connections) {
54886
54996
  function collectNodeFiles(dir) {
54887
54997
  const results = [];
54888
54998
  try {
54889
- const entries = fs71.readdirSync(dir, { withFileTypes: true });
54999
+ const entries = fs72.readdirSync(dir, { withFileTypes: true });
54890
55000
  for (const entry of entries) {
54891
55001
  const fullPath = path83.join(dir, entry.name);
54892
55002
  if (entry.isDirectory()) {
@@ -55148,14 +55258,14 @@ var N8nPlugin = class {
55148
55258
  }
55149
55259
  }
55150
55260
  try {
55151
- if (fs71.existsSync(path83.join(ctx.rootPath, ".n8n"))) return true;
55261
+ if (fs72.existsSync(path83.join(ctx.rootPath, ".n8n"))) return true;
55152
55262
  } catch {
55153
55263
  }
55154
55264
  const nodeDirs = ["nodes", "src/nodes"];
55155
55265
  for (const dir of nodeDirs) {
55156
55266
  try {
55157
55267
  const fullDir = path83.join(ctx.rootPath, dir);
55158
- if (fs71.existsSync(fullDir) && fs71.statSync(fullDir).isDirectory()) {
55268
+ if (fs72.existsSync(fullDir) && fs72.statSync(fullDir).isDirectory()) {
55159
55269
  const files = collectNodeFiles(fullDir);
55160
55270
  if (files.length > 0) return true;
55161
55271
  }
@@ -55166,11 +55276,11 @@ var N8nPlugin = class {
55166
55276
  for (const dir of searchDirs) {
55167
55277
  try {
55168
55278
  const fullDir = path83.join(ctx.rootPath, dir);
55169
- if (!fs71.existsSync(fullDir) || !fs71.statSync(fullDir).isDirectory()) continue;
55170
- const files = fs71.readdirSync(fullDir).filter((f) => f.endsWith(".json"));
55279
+ if (!fs72.existsSync(fullDir) || !fs72.statSync(fullDir).isDirectory()) continue;
55280
+ const files = fs72.readdirSync(fullDir).filter((f) => f.endsWith(".json"));
55171
55281
  for (const file of files.slice(0, 5)) {
55172
55282
  try {
55173
- const content = fs71.readFileSync(path83.join(fullDir, file));
55283
+ const content = fs72.readFileSync(path83.join(fullDir, file));
55174
55284
  if (parseN8nWorkflow(content)) return true;
55175
55285
  } catch {
55176
55286
  }
@@ -55566,7 +55676,7 @@ function findNodeByteOffset(source, nodeName) {
55566
55676
  }
55567
55677
 
55568
55678
  // src/indexer/plugins/integration/tooling/data-fetching/index.ts
55569
- import fs72 from "fs";
55679
+ import fs73 from "fs";
55570
55680
  import path84 from "path";
55571
55681
  var USE_QUERY_OBJECT_RE = /\b(useQuery|useInfiniteQuery)\s*\(\s*\{[^}]*?queryFn\s*:\s*[^}]*?fetch\s*\(\s*[`'"](\/[^'"`$]*?)['"`]/g;
55572
55682
  var USE_QUERY_ARRAY_RE = /\b(useQuery|useInfiniteQuery)\s*\(\s*\[[^\]]*\]\s*,\s*(?:\([^)]*\)\s*=>|function\s*\([^)]*\)\s*\{)[^)]*?fetch\s*\(\s*[`'"](\/[^'"`$]*?)['"`]/g;
@@ -55640,7 +55750,7 @@ var DataFetchingPlugin = class {
55640
55750
  }
55641
55751
  try {
55642
55752
  const pkgPath = path84.join(ctx.rootPath, "package.json");
55643
- const content = fs72.readFileSync(pkgPath, "utf-8");
55753
+ const content = fs73.readFileSync(pkgPath, "utf-8");
55644
55754
  const pkg = JSON.parse(content);
55645
55755
  const deps = {
55646
55756
  ...pkg.dependencies,
@@ -55684,7 +55794,7 @@ var DataFetchingPlugin = class {
55684
55794
  };
55685
55795
 
55686
55796
  // src/indexer/plugins/integration/tooling/commander/index.ts
55687
- import fs73 from "fs";
55797
+ import fs74 from "fs";
55688
55798
  import path85 from "path";
55689
55799
  var CLI_PACKAGES = ["commander", "yargs", "@oclif/core", "clipanion", "cac", "citty"];
55690
55800
  var COMMAND_RE = /\.command\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]*)['"]\s*)?/g;
@@ -55742,7 +55852,7 @@ var CommanderPlugin = class {
55742
55852
  }
55743
55853
  try {
55744
55854
  const pkgPath = path85.join(ctx.rootPath, "package.json");
55745
- const content = fs73.readFileSync(pkgPath, "utf-8");
55855
+ const content = fs74.readFileSync(pkgPath, "utf-8");
55746
55856
  const pkg = JSON.parse(content);
55747
55857
  const deps = {
55748
55858
  ...pkg.dependencies,
@@ -55795,7 +55905,7 @@ var CommanderPlugin = class {
55795
55905
  };
55796
55906
 
55797
55907
  // src/indexer/plugins/integration/tooling/tree-sitter/index.ts
55798
- import fs74 from "fs";
55908
+ import fs75 from "fs";
55799
55909
  import path86 from "path";
55800
55910
  var TREE_SITTER_PACKAGES = [
55801
55911
  "tree-sitter",
@@ -55840,7 +55950,7 @@ var TreeSitterPlugin = class {
55840
55950
  }
55841
55951
  try {
55842
55952
  const pkgPath = path86.join(ctx.rootPath, "package.json");
55843
- const content = fs74.readFileSync(pkgPath, "utf-8");
55953
+ const content = fs75.readFileSync(pkgPath, "utf-8");
55844
55954
  const pkg = JSON.parse(content);
55845
55955
  const deps = {
55846
55956
  ...pkg.dependencies,
@@ -55886,7 +55996,7 @@ var TreeSitterPlugin = class {
55886
55996
  };
55887
55997
 
55888
55998
  // src/indexer/plugins/integration/tooling/build-tools/index.ts
55889
- import fs75 from "fs";
55999
+ import fs76 from "fs";
55890
56000
  import path87 from "path";
55891
56001
  var BUILD_PACKAGES = [
55892
56002
  "tsup",
@@ -55971,7 +56081,7 @@ var BuildToolsPlugin = class {
55971
56081
  }
55972
56082
  try {
55973
56083
  const pkgPath = path87.join(ctx.rootPath, "package.json");
55974
- const content = fs75.readFileSync(pkgPath, "utf-8");
56084
+ const content = fs76.readFileSync(pkgPath, "utf-8");
55975
56085
  const pkg = JSON.parse(content);
55976
56086
  const deps = {
55977
56087
  ...pkg.dependencies,
@@ -56091,7 +56201,7 @@ var GithubActionsPlugin = class {
56091
56201
  };
56092
56202
 
56093
56203
  // src/indexer/plugins/integration/tooling/pino/index.ts
56094
- import fs76 from "fs";
56204
+ import fs77 from "fs";
56095
56205
  import path88 from "path";
56096
56206
  var LOGGING_PACKAGES = ["pino", "winston", "bunyan", "log4js", "pino-pretty", "pino-http"];
56097
56207
  var LOGGER_CREATE_RE = /(?:pino|createLogger|getLogger|winston\.createLogger|bunyan\.createLogger)\s*\(/g;
@@ -56118,7 +56228,7 @@ var PinoPlugin = class {
56118
56228
  }
56119
56229
  try {
56120
56230
  const pkgPath = path88.join(ctx.rootPath, "package.json");
56121
- const content = fs76.readFileSync(pkgPath, "utf-8");
56231
+ const content = fs77.readFileSync(pkgPath, "utf-8");
56122
56232
  const pkg = JSON.parse(content);
56123
56233
  const deps = {
56124
56234
  ...pkg.dependencies,
@@ -56167,7 +56277,7 @@ var PinoPlugin = class {
56167
56277
  };
56168
56278
 
56169
56279
  // src/indexer/plugins/integration/tooling/cosmiconfig/index.ts
56170
- import fs77 from "fs";
56280
+ import fs78 from "fs";
56171
56281
  import path89 from "path";
56172
56282
  var CONFIG_PACKAGES = ["cosmiconfig", "lilconfig", "rc", "dotenv", "envalid", "env-var"];
56173
56283
  var EXPLORER_RE = /(?:cosmiconfig|lilconfig|cosmiconfigSync|lilconfigSync)\(\s*['"]([^'"]+)['"]/g;
@@ -56193,7 +56303,7 @@ var CosmiconfigPlugin = class {
56193
56303
  }
56194
56304
  try {
56195
56305
  const pkgPath = path89.join(ctx.rootPath, "package.json");
56196
- const content = fs77.readFileSync(pkgPath, "utf-8");
56306
+ const content = fs78.readFileSync(pkgPath, "utf-8");
56197
56307
  const pkg = JSON.parse(content);
56198
56308
  const deps = {
56199
56309
  ...pkg.dependencies,
@@ -56238,7 +56348,7 @@ var CosmiconfigPlugin = class {
56238
56348
  };
56239
56349
 
56240
56350
  // src/indexer/plugins/integration/tooling/neverthrow/index.ts
56241
- import fs78 from "fs";
56351
+ import fs79 from "fs";
56242
56352
  import path90 from "path";
56243
56353
  var RESULT_PACKAGES = ["neverthrow", "ts-results", "oxide.ts", "true-myth", "@badrap/result"];
56244
56354
  var RESULT_TYPE_RE = /(?:Result|ResultAsync|Ok|Err)\s*<[^>]+>/g;
@@ -56265,7 +56375,7 @@ var NeverthrowPlugin = class {
56265
56375
  }
56266
56376
  try {
56267
56377
  const pkgPath = path90.join(ctx.rootPath, "package.json");
56268
- const content = fs78.readFileSync(pkgPath, "utf-8");
56378
+ const content = fs79.readFileSync(pkgPath, "utf-8");
56269
56379
  const pkg = JSON.parse(content);
56270
56380
  const deps = {
56271
56381
  ...pkg.dependencies,
@@ -56312,7 +56422,7 @@ var NeverthrowPlugin = class {
56312
56422
  };
56313
56423
 
56314
56424
  // src/indexer/plugins/integration/tooling/clack/index.ts
56315
- import fs79 from "fs";
56425
+ import fs80 from "fs";
56316
56426
  import path91 from "path";
56317
56427
  var PROMPT_PACKAGES = [
56318
56428
  "@clack/prompts",
@@ -56346,7 +56456,7 @@ var ClackPlugin = class {
56346
56456
  }
56347
56457
  try {
56348
56458
  const pkgPath = path91.join(ctx.rootPath, "package.json");
56349
- const content = fs79.readFileSync(pkgPath, "utf-8");
56459
+ const content = fs80.readFileSync(pkgPath, "utf-8");
56350
56460
  const pkg = JSON.parse(content);
56351
56461
  const deps = {
56352
56462
  ...pkg.dependencies,
@@ -56650,12 +56760,12 @@ import http from "http";
56650
56760
 
56651
56761
  // src/cli/init.ts
56652
56762
  import { Command } from "commander";
56653
- import fs89 from "fs";
56763
+ import fs90 from "fs";
56654
56764
  import path102 from "path";
56655
56765
  import * as p from "@clack/prompts";
56656
56766
 
56657
56767
  // src/init/mcp-client.ts
56658
- import fs80 from "fs";
56768
+ import fs81 from "fs";
56659
56769
  import path93 from "path";
56660
56770
  import os5 from "os";
56661
56771
  var HOME = os5.homedir();
@@ -56667,9 +56777,9 @@ function configureMcpClients(clientNames, projectRoot, opts) {
56667
56777
  results.push({ target: name, action: "skipped", detail: "Unknown client" });
56668
56778
  continue;
56669
56779
  }
56670
- if (fs80.existsSync(configPath)) {
56780
+ if (fs81.existsSync(configPath)) {
56671
56781
  try {
56672
- const content = JSON.parse(fs80.readFileSync(configPath, "utf-8"));
56782
+ const content = JSON.parse(fs81.readFileSync(configPath, "utf-8"));
56673
56783
  if (content?.mcpServers?.["trace-mcp"]) {
56674
56784
  results.push({ target: configPath, action: "already_configured", detail: name });
56675
56785
  continue;
@@ -56696,12 +56806,12 @@ function configureMcpClients(clientNames, projectRoot, opts) {
56696
56806
  }
56697
56807
  function writeTraceMcpEntry(configPath, entry) {
56698
56808
  const dir = path93.dirname(configPath);
56699
- if (!fs80.existsSync(dir)) fs80.mkdirSync(dir, { recursive: true });
56809
+ if (!fs81.existsSync(dir)) fs81.mkdirSync(dir, { recursive: true });
56700
56810
  let config = {};
56701
56811
  let isNew = true;
56702
- if (fs80.existsSync(configPath)) {
56812
+ if (fs81.existsSync(configPath)) {
56703
56813
  try {
56704
- config = JSON.parse(fs80.readFileSync(configPath, "utf-8"));
56814
+ config = JSON.parse(fs81.readFileSync(configPath, "utf-8"));
56705
56815
  isNew = false;
56706
56816
  } catch {
56707
56817
  }
@@ -56710,7 +56820,7 @@ function writeTraceMcpEntry(configPath, entry) {
56710
56820
  config.mcpServers = {};
56711
56821
  }
56712
56822
  config.mcpServers["trace-mcp"] = entry;
56713
- fs80.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
56823
+ fs81.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
56714
56824
  return isNew ? "created" : "updated";
56715
56825
  }
56716
56826
  function getConfigPath(name, projectRoot, scope) {
@@ -56733,7 +56843,7 @@ function getConfigPath(name, projectRoot, scope) {
56733
56843
  }
56734
56844
 
56735
56845
  // src/init/claude-md.ts
56736
- import fs81 from "fs";
56846
+ import fs82 from "fs";
56737
56847
  import path94 from "path";
56738
56848
  var START_MARKER = "<!-- trace-mcp:start -->";
56739
56849
  var END_MARKER = "<!-- trace-mcp:end -->";
@@ -56767,20 +56877,20 @@ ${END_MARKER}`;
56767
56877
  function updateClaudeMd(projectRoot, opts) {
56768
56878
  const filePath = opts.scope === "global" ? path94.join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".claude", "CLAUDE.md") : path94.join(projectRoot, "CLAUDE.md");
56769
56879
  if (opts.dryRun) {
56770
- if (!fs81.existsSync(filePath)) {
56880
+ if (!fs82.existsSync(filePath)) {
56771
56881
  return { target: filePath, action: "skipped", detail: "Would create CLAUDE.md" };
56772
56882
  }
56773
- const content2 = fs81.readFileSync(filePath, "utf-8");
56883
+ const content2 = fs82.readFileSync(filePath, "utf-8");
56774
56884
  if (content2.includes(START_MARKER)) {
56775
56885
  return { target: filePath, action: "skipped", detail: "Would update trace-mcp block" };
56776
56886
  }
56777
56887
  return { target: filePath, action: "skipped", detail: "Would append trace-mcp block" };
56778
56888
  }
56779
- if (!fs81.existsSync(filePath)) {
56780
- fs81.writeFileSync(filePath, BLOCK + "\n");
56889
+ if (!fs82.existsSync(filePath)) {
56890
+ fs82.writeFileSync(filePath, BLOCK + "\n");
56781
56891
  return { target: filePath, action: "created" };
56782
56892
  }
56783
- let content = fs81.readFileSync(filePath, "utf-8");
56893
+ let content = fs82.readFileSync(filePath, "utf-8");
56784
56894
  const originalContent = content;
56785
56895
  content = removeCompetingBlocks(content);
56786
56896
  if (content.includes(START_MARKER)) {
@@ -56790,13 +56900,13 @@ function updateClaudeMd(projectRoot, opts) {
56790
56900
  if (content === originalContent) {
56791
56901
  return { target: filePath, action: "already_configured" };
56792
56902
  }
56793
- fs81.writeFileSync(filePath, content);
56903
+ fs82.writeFileSync(filePath, content);
56794
56904
  const cleaned2 = content !== removeCompetingBlocks(originalContent);
56795
56905
  return { target: filePath, action: "updated", detail: cleaned2 ? "Updated trace-mcp block and removed competing sections" : void 0 };
56796
56906
  }
56797
56907
  content = cleanupWhitespace(content);
56798
56908
  const separator = content.endsWith("\n") ? "\n" : "\n\n";
56799
- fs81.writeFileSync(filePath, content + separator + BLOCK + "\n");
56909
+ fs82.writeFileSync(filePath, content + separator + BLOCK + "\n");
56800
56910
  const cleaned = originalContent !== content;
56801
56911
  return { target: filePath, action: "updated", detail: cleaned ? "Appended trace-mcp block and removed competing sections" : "Appended trace-mcp block" };
56802
56912
  }
@@ -56915,7 +57025,7 @@ function escapeRegex4(s) {
56915
57025
  }
56916
57026
 
56917
57027
  // src/init/hooks.ts
56918
- import fs82 from "fs";
57028
+ import fs83 from "fs";
56919
57029
  import path95 from "path";
56920
57030
  import os6 from "os";
56921
57031
 
@@ -56981,7 +57091,7 @@ function settingsPath(client, global) {
56981
57091
  return global ? path95.join(HOME2, client.configDir, "settings.json") : path95.resolve(process.cwd(), client.configDir, "settings.local.json");
56982
57092
  }
56983
57093
  function clientExists(client) {
56984
- return fs82.existsSync(path95.join(HOME2, client.configDir));
57094
+ return fs83.existsSync(path95.join(HOME2, client.configDir));
56985
57095
  }
56986
57096
  function findHookSource(scriptName) {
56987
57097
  const filename = `${scriptName}${HOOK_EXT}`;
@@ -56994,20 +57104,20 @@ function findHookSource(scriptName) {
56994
57104
  path95.resolve(process.cwd(), "hooks", filename)
56995
57105
  ];
56996
57106
  for (const c of candidates) {
56997
- if (fs82.existsSync(c)) return c;
57107
+ if (fs83.existsSync(c)) return c;
56998
57108
  }
56999
57109
  throw new Error(`Could not find hooks/${filename} \u2014 trace-mcp installation may be corrupted.`);
57000
57110
  }
57001
57111
  function ensureDir(dir) {
57002
- if (!fs82.existsSync(dir)) fs82.mkdirSync(dir, { recursive: true });
57112
+ if (!fs83.existsSync(dir)) fs83.mkdirSync(dir, { recursive: true });
57003
57113
  }
57004
57114
  function readSettings(filePath) {
57005
- if (!fs82.existsSync(filePath)) return {};
57006
- return JSON.parse(fs82.readFileSync(filePath, "utf-8"));
57115
+ if (!fs83.existsSync(filePath)) return {};
57116
+ return JSON.parse(fs83.readFileSync(filePath, "utf-8"));
57007
57117
  }
57008
57118
  function writeSettings(filePath, settings) {
57009
57119
  ensureDir(path95.dirname(filePath));
57010
- fs82.writeFileSync(filePath, JSON.stringify(settings, null, 2) + "\n");
57120
+ fs83.writeFileSync(filePath, JSON.stringify(settings, null, 2) + "\n");
57011
57121
  }
57012
57122
  function addHookEntry(settings, desc, dest) {
57013
57123
  const hooks = settings.hooks ?? {};
@@ -57046,13 +57156,13 @@ function installHook(desc, opts) {
57046
57156
  return { target: primaryDest, action: "skipped", detail: desc.dryRunLabel };
57047
57157
  }
57048
57158
  const hookSrc = findHookSource(desc.scriptName);
57049
- const isUpdate = fs82.existsSync(primaryDest);
57159
+ const isUpdate = fs83.existsSync(primaryDest);
57050
57160
  for (const client of CLIENTS) {
57051
57161
  if (client !== CLIENTS[0] && !clientExists(client)) continue;
57052
57162
  const dest = hookDest(client, desc);
57053
57163
  ensureDir(path95.dirname(dest));
57054
- fs82.copyFileSync(hookSrc, dest);
57055
- if (!IS_WINDOWS) fs82.chmodSync(dest, 493);
57164
+ fs83.copyFileSync(hookSrc, dest);
57165
+ if (!IS_WINDOWS) fs83.chmodSync(dest, 493);
57056
57166
  const sPath = settingsPath(client, !!opts.global);
57057
57167
  const settings = readSettings(sPath);
57058
57168
  addHookEntry(settings, desc, dest);
@@ -57067,13 +57177,13 @@ function installHook(desc, opts) {
57067
57177
  function uninstallHook(desc, opts) {
57068
57178
  for (const client of CLIENTS) {
57069
57179
  const sPath = settingsPath(client, !!opts.global);
57070
- if (fs82.existsSync(sPath)) {
57180
+ if (fs83.existsSync(sPath)) {
57071
57181
  const settings = readSettings(sPath);
57072
57182
  removeHookEntry(settings, desc);
57073
57183
  writeSettings(sPath, settings);
57074
57184
  }
57075
57185
  const dest = hookDest(client, desc);
57076
- if (fs82.existsSync(dest)) fs82.unlinkSync(dest);
57186
+ if (fs83.existsSync(dest)) fs83.unlinkSync(dest);
57077
57187
  }
57078
57188
  return { target: hookDest(CLIENTS[0], desc), action: "updated", detail: "Removed" };
57079
57189
  }
@@ -57101,7 +57211,7 @@ function installWorktreeHook(opts) {
57101
57211
  }
57102
57212
 
57103
57213
  // src/init/ide-rules.ts
57104
- import fs83 from "fs";
57214
+ import fs84 from "fs";
57105
57215
  import path96 from "path";
57106
57216
  var START_MARKER2 = "<!-- trace-mcp:start -->";
57107
57217
  var END_MARKER2 = "<!-- trace-mcp:end -->";
@@ -57142,8 +57252,8 @@ function installCursorRules(projectRoot, opts) {
57142
57252
  const rulesDir = path96.join(base, "rules");
57143
57253
  const filePath = path96.join(rulesDir, "trace-mcp.mdc");
57144
57254
  if (opts.dryRun) {
57145
- if (fs83.existsSync(filePath)) {
57146
- const content = fs83.readFileSync(filePath, "utf-8");
57255
+ if (fs84.existsSync(filePath)) {
57256
+ const content = fs84.readFileSync(filePath, "utf-8");
57147
57257
  if (content === CURSOR_RULE) {
57148
57258
  return { target: filePath, action: "skipped", detail: "Already up to date" };
57149
57259
  }
@@ -57151,16 +57261,16 @@ function installCursorRules(projectRoot, opts) {
57151
57261
  }
57152
57262
  return { target: filePath, action: "skipped", detail: "Would create trace-mcp.mdc" };
57153
57263
  }
57154
- if (fs83.existsSync(filePath)) {
57155
- const content = fs83.readFileSync(filePath, "utf-8");
57264
+ if (fs84.existsSync(filePath)) {
57265
+ const content = fs84.readFileSync(filePath, "utf-8");
57156
57266
  if (content === CURSOR_RULE) {
57157
57267
  return { target: filePath, action: "already_configured" };
57158
57268
  }
57159
- fs83.writeFileSync(filePath, CURSOR_RULE);
57269
+ fs84.writeFileSync(filePath, CURSOR_RULE);
57160
57270
  return { target: filePath, action: "updated" };
57161
57271
  }
57162
- fs83.mkdirSync(rulesDir, { recursive: true });
57163
- fs83.writeFileSync(filePath, CURSOR_RULE);
57272
+ fs84.mkdirSync(rulesDir, { recursive: true });
57273
+ fs84.writeFileSync(filePath, CURSOR_RULE);
57164
57274
  return { target: filePath, action: "created" };
57165
57275
  }
57166
57276
  var WINDSURF_BLOCK = `${START_MARKER2}
@@ -57171,31 +57281,31 @@ ${END_MARKER2}`;
57171
57281
  function installWindsurfRules(projectRoot, opts) {
57172
57282
  const filePath = opts.global ? path96.join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".windsurfrules") : path96.join(projectRoot, ".windsurfrules");
57173
57283
  if (opts.dryRun) {
57174
- if (!fs83.existsSync(filePath)) {
57284
+ if (!fs84.existsSync(filePath)) {
57175
57285
  return { target: filePath, action: "skipped", detail: "Would create .windsurfrules" };
57176
57286
  }
57177
- const content2 = fs83.readFileSync(filePath, "utf-8");
57287
+ const content2 = fs84.readFileSync(filePath, "utf-8");
57178
57288
  if (content2.includes(START_MARKER2)) {
57179
57289
  return { target: filePath, action: "skipped", detail: "Would update trace-mcp block" };
57180
57290
  }
57181
57291
  return { target: filePath, action: "skipped", detail: "Would append trace-mcp block" };
57182
57292
  }
57183
- if (!fs83.existsSync(filePath)) {
57184
- fs83.writeFileSync(filePath, WINDSURF_BLOCK + "\n");
57293
+ if (!fs84.existsSync(filePath)) {
57294
+ fs84.writeFileSync(filePath, WINDSURF_BLOCK + "\n");
57185
57295
  return { target: filePath, action: "created" };
57186
57296
  }
57187
- const content = fs83.readFileSync(filePath, "utf-8");
57297
+ const content = fs84.readFileSync(filePath, "utf-8");
57188
57298
  if (content.includes(START_MARKER2)) {
57189
57299
  const re = new RegExp(`${escapeRegex5(START_MARKER2)}[\\s\\S]*?${escapeRegex5(END_MARKER2)}`, "m");
57190
57300
  const updated = content.replace(re, WINDSURF_BLOCK);
57191
57301
  if (updated === content) {
57192
57302
  return { target: filePath, action: "already_configured" };
57193
57303
  }
57194
- fs83.writeFileSync(filePath, updated);
57304
+ fs84.writeFileSync(filePath, updated);
57195
57305
  return { target: filePath, action: "updated" };
57196
57306
  }
57197
57307
  const separator = content.endsWith("\n") ? "\n" : "\n\n";
57198
- fs83.writeFileSync(filePath, content + separator + WINDSURF_BLOCK + "\n");
57308
+ fs84.writeFileSync(filePath, content + separator + WINDSURF_BLOCK + "\n");
57199
57309
  return { target: filePath, action: "updated", detail: "Appended trace-mcp block" };
57200
57310
  }
57201
57311
  function escapeRegex5(s) {
@@ -57203,7 +57313,7 @@ function escapeRegex5(s) {
57203
57313
  }
57204
57314
 
57205
57315
  // src/init/detector.ts
57206
- import fs84 from "fs";
57316
+ import fs85 from "fs";
57207
57317
  import path97 from "path";
57208
57318
  import os7 from "os";
57209
57319
  import Database6 from "better-sqlite3";
@@ -57239,8 +57349,8 @@ function detectProject(dir) {
57239
57349
  const existingConfig = detectExistingConfig(projectRoot);
57240
57350
  const existingDb = detectExistingDb(projectRoot);
57241
57351
  const claudeMdPath = path97.join(projectRoot, "CLAUDE.md");
57242
- const hasClaudeMd = fs84.existsSync(claudeMdPath);
57243
- const claudeMdHasTraceMcpBlock = hasClaudeMd && fs84.readFileSync(claudeMdPath, "utf-8").includes("<!-- trace-mcp:start -->");
57352
+ const hasClaudeMd = fs85.existsSync(claudeMdPath);
57353
+ const claudeMdHasTraceMcpBlock = hasClaudeMd && fs85.readFileSync(claudeMdPath, "utf-8").includes("<!-- trace-mcp:start -->");
57244
57354
  const { hasGuardHook, guardHookVersion } = detectGuardHook();
57245
57355
  return {
57246
57356
  projectRoot,
@@ -57259,8 +57369,8 @@ function detectProject(dir) {
57259
57369
  function detectPackageManagers(root) {
57260
57370
  const managers = [];
57261
57371
  const check = (file, type, lockfiles) => {
57262
- if (fs84.existsSync(path97.join(root, file))) {
57263
- const lockfile = lockfiles.find((l) => fs84.existsSync(path97.join(root, l)));
57372
+ if (fs85.existsSync(path97.join(root, file))) {
57373
+ const lockfile = lockfiles.find((l) => fs85.existsSync(path97.join(root, l)));
57264
57374
  managers.push({ type, lockfile });
57265
57375
  }
57266
57376
  };
@@ -57274,7 +57384,7 @@ function detectPackageManagers(root) {
57274
57384
  check("pyproject.toml", "poetry", ["poetry.lock", "uv.lock"]);
57275
57385
  if (managers.length > 0 && managers[managers.length - 1].type === "poetry") {
57276
57386
  if (managers[managers.length - 1].lockfile === "uv.lock") managers[managers.length - 1].type = "uv";
57277
- else if (!managers[managers.length - 1].lockfile && fs84.existsSync(path97.join(root, "requirements.txt"))) {
57387
+ else if (!managers[managers.length - 1].lockfile && fs85.existsSync(path97.join(root, "requirements.txt"))) {
57278
57388
  managers[managers.length - 1].type = "pip";
57279
57389
  }
57280
57390
  }
@@ -57283,7 +57393,7 @@ function detectPackageManagers(root) {
57283
57393
  check("Gemfile", "bundler", ["Gemfile.lock"]);
57284
57394
  check("pom.xml", "maven", []);
57285
57395
  if (!managers.some((m) => m.type === "maven")) {
57286
- if (fs84.existsSync(path97.join(root, "build.gradle")) || fs84.existsSync(path97.join(root, "build.gradle.kts"))) {
57396
+ if (fs85.existsSync(path97.join(root, "build.gradle")) || fs85.existsSync(path97.join(root, "build.gradle.kts"))) {
57287
57397
  managers.push({ type: "gradle", lockfile: void 0 });
57288
57398
  }
57289
57399
  }
@@ -57292,9 +57402,9 @@ function detectPackageManagers(root) {
57292
57402
  function detectMcpClients(projectRoot) {
57293
57403
  const clients = [];
57294
57404
  const checkConfig = (name, configPath) => {
57295
- if (!fs84.existsSync(configPath)) return;
57405
+ if (!fs85.existsSync(configPath)) return;
57296
57406
  try {
57297
- const content = JSON.parse(fs84.readFileSync(configPath, "utf-8"));
57407
+ const content = JSON.parse(fs85.readFileSync(configPath, "utf-8"));
57298
57408
  const hasTraceMcp = !!content?.mcpServers?.["trace-mcp"];
57299
57409
  clients.push({ name, configPath, hasTraceMcp });
57300
57410
  } catch {
@@ -57337,12 +57447,12 @@ function detectExistingConfig(root) {
57337
57447
  path97.join(root, ".config", "trace-mcp.json")
57338
57448
  ];
57339
57449
  for (const p5 of candidates) {
57340
- if (fs84.existsSync(p5)) return { path: p5 };
57450
+ if (fs85.existsSync(p5)) return { path: p5 };
57341
57451
  }
57342
57452
  const pkgPath = path97.join(root, "package.json");
57343
- if (fs84.existsSync(pkgPath)) {
57453
+ if (fs85.existsSync(pkgPath)) {
57344
57454
  try {
57345
- const pkg = JSON.parse(fs84.readFileSync(pkgPath, "utf-8"));
57455
+ const pkg = JSON.parse(fs85.readFileSync(pkgPath, "utf-8"));
57346
57456
  if (pkg["trace-mcp"]) return { path: pkgPath };
57347
57457
  } catch {
57348
57458
  }
@@ -57351,7 +57461,7 @@ function detectExistingConfig(root) {
57351
57461
  }
57352
57462
  function detectExistingDb(root, globalDbPath) {
57353
57463
  const candidates = globalDbPath ? [globalDbPath, path97.join(root, ".trace-mcp", "index.db")] : [path97.join(root, ".trace-mcp", "index.db")];
57354
- const dbPath = candidates.find((p5) => fs84.existsSync(p5));
57464
+ const dbPath = candidates.find((p5) => fs85.existsSync(p5));
57355
57465
  if (!dbPath) return null;
57356
57466
  try {
57357
57467
  const db = new Database6(dbPath, { readonly: true });
@@ -57369,9 +57479,9 @@ function detectGuardHook() {
57369
57479
  const ext = process.platform === "win32" ? ".cmd" : ".sh";
57370
57480
  const hookPath = path97.join(HOME3, ".claude", "hooks", `trace-mcp-guard${ext}`);
57371
57481
  const clawHookPath = path97.join(HOME3, ".claw", "hooks", `trace-mcp-guard${ext}`);
57372
- const existingPath = fs84.existsSync(hookPath) ? hookPath : fs84.existsSync(clawHookPath) ? clawHookPath : null;
57482
+ const existingPath = fs85.existsSync(hookPath) ? hookPath : fs85.existsSync(clawHookPath) ? clawHookPath : null;
57373
57483
  if (!existingPath) return { hasGuardHook: false, guardHookVersion: null };
57374
- const content = fs84.readFileSync(existingPath, "utf-8");
57484
+ const content = fs85.readFileSync(existingPath, "utf-8");
57375
57485
  const match = content.match(/^(?:#|REM) trace-mcp-guard v(.+)$/m);
57376
57486
  return {
57377
57487
  hasGuardHook: true,
@@ -57380,7 +57490,7 @@ function detectGuardHook() {
57380
57490
  }
57381
57491
 
57382
57492
  // src/init/conflict-detector.ts
57383
- import fs85 from "fs";
57493
+ import fs86 from "fs";
57384
57494
  import path98 from "path";
57385
57495
  import os8 from "os";
57386
57496
  var HOME4 = os8.homedir();
@@ -57507,10 +57617,10 @@ function scanMcpServerConfigs(projectRoot) {
57507
57617
  const conflicts = [];
57508
57618
  const configs = getMcpConfigPaths(projectRoot);
57509
57619
  for (const { clientName, configPath } of configs) {
57510
- if (!fs85.existsSync(configPath)) continue;
57620
+ if (!fs86.existsSync(configPath)) continue;
57511
57621
  let parsed;
57512
57622
  try {
57513
- parsed = JSON.parse(fs85.readFileSync(configPath, "utf-8"));
57623
+ parsed = JSON.parse(fs86.readFileSync(configPath, "utf-8"));
57514
57624
  } catch {
57515
57625
  continue;
57516
57626
  }
@@ -57570,12 +57680,12 @@ function scanHooksInSettings() {
57570
57680
  path98.join(HOME4, ".claw", "settings.local.json")
57571
57681
  ];
57572
57682
  const projectsDir = path98.join(HOME4, ".claude", "projects");
57573
- if (fs85.existsSync(projectsDir)) {
57683
+ if (fs86.existsSync(projectsDir)) {
57574
57684
  try {
57575
- for (const entry of fs85.readdirSync(projectsDir)) {
57685
+ for (const entry of fs86.readdirSync(projectsDir)) {
57576
57686
  const projDir = path98.join(projectsDir, entry);
57577
57687
  try {
57578
- if (!fs85.statSync(projDir).isDirectory()) continue;
57688
+ if (!fs86.statSync(projDir).isDirectory()) continue;
57579
57689
  } catch {
57580
57690
  continue;
57581
57691
  }
@@ -57586,10 +57696,10 @@ function scanHooksInSettings() {
57586
57696
  }
57587
57697
  }
57588
57698
  for (const settingsPath2 of settingsFiles) {
57589
- if (!fs85.existsSync(settingsPath2)) continue;
57699
+ if (!fs86.existsSync(settingsPath2)) continue;
57590
57700
  let settings;
57591
57701
  try {
57592
- settings = JSON.parse(fs85.readFileSync(settingsPath2, "utf-8"));
57702
+ settings = JSON.parse(fs86.readFileSync(settingsPath2, "utf-8"));
57593
57703
  } catch {
57594
57704
  continue;
57595
57705
  }
@@ -57631,10 +57741,10 @@ function scanHookScriptFiles() {
57631
57741
  path98.join(HOME4, ".claw", "hooks")
57632
57742
  ];
57633
57743
  for (const hooksDir of hooksDirs) {
57634
- if (!fs85.existsSync(hooksDir)) continue;
57744
+ if (!fs86.existsSync(hooksDir)) continue;
57635
57745
  let files;
57636
57746
  try {
57637
- files = fs85.readdirSync(hooksDir);
57747
+ files = fs86.readdirSync(hooksDir);
57638
57748
  } catch {
57639
57749
  continue;
57640
57750
  }
@@ -57667,17 +57777,17 @@ function scanClaudeMdFiles(projectRoot) {
57667
57777
  path98.join(HOME4, ".claude", "AGENTS.md")
57668
57778
  ];
57669
57779
  const projectsDir = path98.join(HOME4, ".claude", "projects");
57670
- if (fs85.existsSync(projectsDir)) {
57780
+ if (fs86.existsSync(projectsDir)) {
57671
57781
  try {
57672
- for (const entry of fs85.readdirSync(projectsDir)) {
57782
+ for (const entry of fs86.readdirSync(projectsDir)) {
57673
57783
  const projDir = path98.join(projectsDir, entry);
57674
- if (!fs85.statSync(projDir).isDirectory()) continue;
57784
+ if (!fs86.statSync(projDir).isDirectory()) continue;
57675
57785
  files.push(path98.join(projDir, "CLAUDE.md"));
57676
57786
  files.push(path98.join(projDir, "AGENTS.md"));
57677
57787
  const memDir = path98.join(projDir, "memory");
57678
- if (fs85.existsSync(memDir)) {
57788
+ if (fs86.existsSync(memDir)) {
57679
57789
  try {
57680
- for (const memFile of fs85.readdirSync(memDir)) {
57790
+ for (const memFile of fs86.readdirSync(memDir)) {
57681
57791
  if (memFile.endsWith(".md") && memFile !== "MEMORY.md") {
57682
57792
  files.push(path98.join(memDir, memFile));
57683
57793
  }
@@ -57696,10 +57806,10 @@ function scanClaudeMdFiles(projectRoot) {
57696
57806
  );
57697
57807
  }
57698
57808
  for (const filePath of files) {
57699
- if (!fs85.existsSync(filePath)) continue;
57809
+ if (!fs86.existsSync(filePath)) continue;
57700
57810
  let content;
57701
57811
  try {
57702
- content = fs85.readFileSync(filePath, "utf-8");
57812
+ content = fs86.readFileSync(filePath, "utf-8");
57703
57813
  } catch {
57704
57814
  continue;
57705
57815
  }
@@ -57756,11 +57866,11 @@ function scanIdeRuleFiles(projectRoot) {
57756
57866
  ruleFiles.push({ path: path98.join(projectRoot, ".continuerules"), type: ".continuerules" });
57757
57867
  ruleFiles.push({ path: path98.join(projectRoot, ".github", "copilot-instructions.md"), type: "copilot-instructions.md" });
57758
57868
  const clineRulesDir = path98.join(projectRoot, ".clinerules");
57759
- if (fs85.existsSync(clineRulesDir)) {
57869
+ if (fs86.existsSync(clineRulesDir)) {
57760
57870
  try {
57761
- const stat = fs85.statSync(clineRulesDir);
57871
+ const stat = fs86.statSync(clineRulesDir);
57762
57872
  if (stat.isDirectory()) {
57763
- for (const file of fs85.readdirSync(clineRulesDir)) {
57873
+ for (const file of fs86.readdirSync(clineRulesDir)) {
57764
57874
  ruleFiles.push({ path: path98.join(clineRulesDir, file), type: `.clinerules/${file}` });
57765
57875
  }
57766
57876
  }
@@ -57771,9 +57881,9 @@ function scanIdeRuleFiles(projectRoot) {
57771
57881
  const cursorRulesDirs = [path98.join(HOME4, ".cursor", "rules")];
57772
57882
  if (projectRoot) cursorRulesDirs.push(path98.join(projectRoot, ".cursor", "rules"));
57773
57883
  for (const rulesDir of cursorRulesDirs) {
57774
- if (!fs85.existsSync(rulesDir)) continue;
57884
+ if (!fs86.existsSync(rulesDir)) continue;
57775
57885
  try {
57776
- for (const file of fs85.readdirSync(rulesDir)) {
57886
+ for (const file of fs86.readdirSync(rulesDir)) {
57777
57887
  if (!file.endsWith(".mdc") || file === "trace-mcp.mdc") continue;
57778
57888
  ruleFiles.push({ path: path98.join(rulesDir, file), type: `.cursor/rules/${file}` });
57779
57889
  }
@@ -57781,10 +57891,10 @@ function scanIdeRuleFiles(projectRoot) {
57781
57891
  }
57782
57892
  }
57783
57893
  for (const { path: filePath, type } of ruleFiles) {
57784
- if (!fs85.existsSync(filePath)) continue;
57894
+ if (!fs86.existsSync(filePath)) continue;
57785
57895
  let content;
57786
57896
  try {
57787
- content = fs85.readFileSync(filePath, "utf-8");
57897
+ content = fs86.readFileSync(filePath, "utf-8");
57788
57898
  } catch {
57789
57899
  continue;
57790
57900
  }
@@ -57810,7 +57920,7 @@ function scanProjectConfigFiles(projectRoot) {
57810
57920
  const conflicts = [];
57811
57921
  for (const { file, competitor } of COMPETING_PROJECT_FILES) {
57812
57922
  const filePath = path98.join(projectRoot, file);
57813
- if (!fs85.existsSync(filePath)) continue;
57923
+ if (!fs86.existsSync(filePath)) continue;
57814
57924
  conflicts.push({
57815
57925
  id: `config:${competitor}:${file}`,
57816
57926
  category: "config_file",
@@ -57834,10 +57944,10 @@ function scanProjectConfigDirs(projectRoot) {
57834
57944
  ];
57835
57945
  for (const { dir, competitor } of dirs) {
57836
57946
  const fullPath = path98.join(projectRoot, dir);
57837
- if (!fs85.existsSync(fullPath)) continue;
57947
+ if (!fs86.existsSync(fullPath)) continue;
57838
57948
  let stat;
57839
57949
  try {
57840
- stat = fs85.statSync(fullPath);
57950
+ stat = fs86.statSync(fullPath);
57841
57951
  } catch {
57842
57952
  continue;
57843
57953
  }
@@ -57873,10 +57983,10 @@ function scanContinueConfigs(projectRoot) {
57873
57983
  mcpServersDirs.push(path98.join(projectRoot, ".continue", "mcpServers"));
57874
57984
  }
57875
57985
  for (const mcpDir of mcpServersDirs) {
57876
- if (!fs85.existsSync(mcpDir)) continue;
57986
+ if (!fs86.existsSync(mcpDir)) continue;
57877
57987
  let files;
57878
57988
  try {
57879
- files = fs85.readdirSync(mcpDir);
57989
+ files = fs86.readdirSync(mcpDir);
57880
57990
  } catch {
57881
57991
  continue;
57882
57992
  }
@@ -57885,7 +57995,7 @@ function scanContinueConfigs(projectRoot) {
57885
57995
  const filePath = path98.join(mcpDir, file);
57886
57996
  let content;
57887
57997
  try {
57888
- content = fs85.readFileSync(filePath, "utf-8");
57998
+ content = fs86.readFileSync(filePath, "utf-8");
57889
57999
  } catch {
57890
58000
  continue;
57891
58001
  }
@@ -57912,14 +58022,14 @@ function scanContinueConfigs(projectRoot) {
57912
58022
  function scanGitHooks(projectRoot) {
57913
58023
  const conflicts = [];
57914
58024
  const hooksDir = path98.join(projectRoot, ".git", "hooks");
57915
- if (!fs85.existsSync(hooksDir)) return conflicts;
58025
+ if (!fs86.existsSync(hooksDir)) return conflicts;
57916
58026
  const hookFiles = ["pre-commit", "post-commit", "prepare-commit-msg"];
57917
58027
  for (const hookFile of hookFiles) {
57918
58028
  const hookPath = path98.join(hooksDir, hookFile);
57919
- if (!fs85.existsSync(hookPath)) continue;
58029
+ if (!fs86.existsSync(hookPath)) continue;
57920
58030
  let content;
57921
58031
  try {
57922
- content = fs85.readFileSync(hookPath, "utf-8");
58032
+ content = fs86.readFileSync(hookPath, "utf-8");
57923
58033
  } catch {
57924
58034
  continue;
57925
58035
  }
@@ -57942,10 +58052,10 @@ function scanGitHooks(projectRoot) {
57942
58052
  function scanGlobalArtifacts() {
57943
58053
  const conflicts = [];
57944
58054
  for (const { dir, competitor } of COMPETING_GLOBAL_DIRS) {
57945
- if (!fs85.existsSync(dir)) continue;
58055
+ if (!fs86.existsSync(dir)) continue;
57946
58056
  let size = 0;
57947
58057
  try {
57948
- const files = fs85.readdirSync(dir);
58058
+ const files = fs86.readdirSync(dir);
57949
58059
  size = files.length;
57950
58060
  } catch {
57951
58061
  }
@@ -57971,7 +58081,7 @@ function truncate(s, maxLen) {
57971
58081
  }
57972
58082
 
57973
58083
  // src/init/conflict-resolver.ts
57974
- import fs86 from "fs";
58084
+ import fs87 from "fs";
57975
58085
  import path99 from "path";
57976
58086
  function fixConflict(conflict, opts = {}) {
57977
58087
  if (!conflict.fixable) {
@@ -58008,16 +58118,16 @@ function fixMcpServer(conflict, opts) {
58008
58118
  if (opts.dryRun) {
58009
58119
  return { conflictId: conflict.id, action: "disabled", detail: `Would comment out "${serverName}" in ${shortPath2(configPath)}`, target: configPath };
58010
58120
  }
58011
- if (!fs86.existsSync(configPath)) {
58121
+ if (!fs87.existsSync(configPath)) {
58012
58122
  return { conflictId: conflict.id, action: "skipped", detail: "Config file no longer exists", target: configPath };
58013
58123
  }
58014
58124
  try {
58015
- const raw = fs86.readFileSync(configPath, "utf-8");
58125
+ const raw = fs87.readFileSync(configPath, "utf-8");
58016
58126
  const result = commentOutJsonKey(raw, serverName);
58017
58127
  if (!result) {
58018
58128
  return { conflictId: conflict.id, action: "skipped", detail: `Server "${serverName}" not found (already disabled?)`, target: configPath };
58019
58129
  }
58020
- fs86.writeFileSync(configPath, result);
58130
+ fs87.writeFileSync(configPath, result);
58021
58131
  return { conflictId: conflict.id, action: "disabled", detail: `Commented out "${serverName}" in ${shortPath2(configPath)}`, target: configPath };
58022
58132
  } catch (err32) {
58023
58133
  return { conflictId: conflict.id, action: "skipped", detail: `Failed to update config: ${err32.message}`, target: configPath };
@@ -58069,11 +58179,11 @@ function fixHookInSettings(conflict, opts) {
58069
58179
  if (opts.dryRun) {
58070
58180
  return { conflictId: conflict.id, action: "removed", detail: `Would remove ${competitor} hooks from ${shortPath2(settingsPath2)}`, target: settingsPath2 };
58071
58181
  }
58072
- if (!fs86.existsSync(settingsPath2)) {
58182
+ if (!fs87.existsSync(settingsPath2)) {
58073
58183
  return { conflictId: conflict.id, action: "skipped", detail: "Settings file no longer exists", target: settingsPath2 };
58074
58184
  }
58075
58185
  try {
58076
- const settings = JSON.parse(fs86.readFileSync(settingsPath2, "utf-8"));
58186
+ const settings = JSON.parse(fs87.readFileSync(settingsPath2, "utf-8"));
58077
58187
  const hooks = settings.hooks;
58078
58188
  if (!hooks) {
58079
58189
  return { conflictId: conflict.id, action: "skipped", detail: "No hooks section found", target: settingsPath2 };
@@ -58101,7 +58211,7 @@ function fixHookInSettings(conflict, opts) {
58101
58211
  if (!modified) {
58102
58212
  return { conflictId: conflict.id, action: "skipped", detail: "Hook entries already removed", target: settingsPath2 };
58103
58213
  }
58104
- fs86.writeFileSync(settingsPath2, JSON.stringify(settings, null, 2) + "\n");
58214
+ fs87.writeFileSync(settingsPath2, JSON.stringify(settings, null, 2) + "\n");
58105
58215
  return { conflictId: conflict.id, action: "removed", detail: `Removed ${competitor} hooks from ${shortPath2(settingsPath2)}`, target: settingsPath2 };
58106
58216
  } catch (err32) {
58107
58217
  return { conflictId: conflict.id, action: "skipped", detail: `Failed to update settings: ${err32.message}`, target: settingsPath2 };
@@ -58112,11 +58222,11 @@ function fixHookScript(conflict, opts) {
58112
58222
  if (opts.dryRun) {
58113
58223
  return { conflictId: conflict.id, action: "removed", detail: `Would delete ${shortPath2(scriptPath)}`, target: scriptPath };
58114
58224
  }
58115
- if (!fs86.existsSync(scriptPath)) {
58225
+ if (!fs87.existsSync(scriptPath)) {
58116
58226
  return { conflictId: conflict.id, action: "skipped", detail: "Script already removed", target: scriptPath };
58117
58227
  }
58118
58228
  try {
58119
- fs86.unlinkSync(scriptPath);
58229
+ fs87.unlinkSync(scriptPath);
58120
58230
  return { conflictId: conflict.id, action: "removed", detail: `Deleted ${shortPath2(scriptPath)}`, target: scriptPath };
58121
58231
  } catch (err32) {
58122
58232
  return { conflictId: conflict.id, action: "skipped", detail: `Failed to delete: ${err32.message}`, target: scriptPath };
@@ -58127,11 +58237,11 @@ function fixClaudeMdBlock(conflict, opts) {
58127
58237
  if (opts.dryRun) {
58128
58238
  return { conflictId: conflict.id, action: "cleaned", detail: `Would remove ${conflict.competitor} content from ${shortPath2(filePath)}`, target: filePath };
58129
58239
  }
58130
- if (!fs86.existsSync(filePath)) {
58240
+ if (!fs87.existsSync(filePath)) {
58131
58241
  return { conflictId: conflict.id, action: "skipped", detail: "File no longer exists", target: filePath };
58132
58242
  }
58133
58243
  try {
58134
- const content = fs86.readFileSync(filePath, "utf-8");
58244
+ const content = fs87.readFileSync(filePath, "utf-8");
58135
58245
  const tools = ["jcodemunch", "code-index", "repomix", "aider", "cline", "cody", "greptile", "sourcegraph", "code-compass", "repo-map"];
58136
58246
  const markerPattern = new RegExp(
58137
58247
  `<!-- ?(${tools.join("|")}):start ?-->[\\s\\S]*?<!-- ?\\1:end ?-->\\n?`,
@@ -58140,7 +58250,7 @@ function fixClaudeMdBlock(conflict, opts) {
58140
58250
  let updated = content.replace(markerPattern, "");
58141
58251
  updated = removeCompetitorSections(updated, conflict.competitor);
58142
58252
  if (filePath.includes("/memory/") && isEntirelyAboutCompetitor(updated, conflict.competitor)) {
58143
- fs86.unlinkSync(filePath);
58253
+ fs87.unlinkSync(filePath);
58144
58254
  removeFromMemoryIndex(filePath);
58145
58255
  return { conflictId: conflict.id, action: "removed", detail: `Deleted memory file ${shortPath2(filePath)}`, target: filePath };
58146
58256
  }
@@ -58148,7 +58258,7 @@ function fixClaudeMdBlock(conflict, opts) {
58148
58258
  if (updated === content) {
58149
58259
  return { conflictId: conflict.id, action: "skipped", detail: "No competing content found to remove", target: filePath };
58150
58260
  }
58151
- fs86.writeFileSync(filePath, updated);
58261
+ fs87.writeFileSync(filePath, updated);
58152
58262
  return { conflictId: conflict.id, action: "cleaned", detail: `Removed ${conflict.competitor} content from ${shortPath2(filePath)}`, target: filePath };
58153
58263
  } catch (err32) {
58154
58264
  return { conflictId: conflict.id, action: "skipped", detail: `Failed to update: ${err32.message}`, target: filePath };
@@ -58200,14 +58310,14 @@ function isEntirelyAboutCompetitor(content, competitor) {
58200
58310
  function removeFromMemoryIndex(deletedFilePath) {
58201
58311
  const memoryDir = path99.dirname(deletedFilePath);
58202
58312
  const indexPath = path99.join(memoryDir, "MEMORY.md");
58203
- if (!fs86.existsSync(indexPath)) return;
58313
+ if (!fs87.existsSync(indexPath)) return;
58204
58314
  try {
58205
- const content = fs86.readFileSync(indexPath, "utf-8");
58315
+ const content = fs87.readFileSync(indexPath, "utf-8");
58206
58316
  const fileName = path99.basename(deletedFilePath);
58207
58317
  const escaped = fileName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58208
58318
  const updated = content.split("\n").filter((line) => !new RegExp(`\\(${escaped}\\)`).test(line)).join("\n");
58209
58319
  if (updated !== content) {
58210
- fs86.writeFileSync(indexPath, updated);
58320
+ fs87.writeFileSync(indexPath, updated);
58211
58321
  }
58212
58322
  } catch {
58213
58323
  }
@@ -58217,15 +58327,15 @@ function fixConfigFile(conflict, opts) {
58217
58327
  if (opts.dryRun) {
58218
58328
  return { conflictId: conflict.id, action: "removed", detail: `Would delete ${shortPath2(filePath)}`, target: filePath };
58219
58329
  }
58220
- if (!fs86.existsSync(filePath)) {
58330
+ if (!fs87.existsSync(filePath)) {
58221
58331
  return { conflictId: conflict.id, action: "skipped", detail: "Already removed", target: filePath };
58222
58332
  }
58223
58333
  try {
58224
- const stat = fs86.statSync(filePath);
58334
+ const stat = fs87.statSync(filePath);
58225
58335
  if (stat.isDirectory()) {
58226
- fs86.rmSync(filePath, { recursive: true, force: true });
58336
+ fs87.rmSync(filePath, { recursive: true, force: true });
58227
58337
  } else {
58228
- fs86.unlinkSync(filePath);
58338
+ fs87.unlinkSync(filePath);
58229
58339
  }
58230
58340
  return { conflictId: conflict.id, action: "removed", detail: `Deleted ${shortPath2(filePath)}`, target: filePath };
58231
58341
  } catch (err32) {
@@ -58237,11 +58347,11 @@ function fixGlobalArtifact(conflict, opts) {
58237
58347
  if (opts.dryRun) {
58238
58348
  return { conflictId: conflict.id, action: "removed", detail: `Would remove ${shortPath2(dirPath)}`, target: dirPath };
58239
58349
  }
58240
- if (!fs86.existsSync(dirPath)) {
58350
+ if (!fs87.existsSync(dirPath)) {
58241
58351
  return { conflictId: conflict.id, action: "skipped", detail: "Directory already removed", target: dirPath };
58242
58352
  }
58243
58353
  try {
58244
- fs86.rmSync(dirPath, { recursive: true, force: true });
58354
+ fs87.rmSync(dirPath, { recursive: true, force: true });
58245
58355
  return { conflictId: conflict.id, action: "removed", detail: `Removed ${shortPath2(dirPath)}`, target: dirPath };
58246
58356
  } catch (err32) {
58247
58357
  return { conflictId: conflict.id, action: "skipped", detail: `Failed to remove: ${err32.message}`, target: dirPath };
@@ -58254,7 +58364,7 @@ function shortPath2(p5) {
58254
58364
  }
58255
58365
 
58256
58366
  // src/project-root.ts
58257
- import fs87 from "fs";
58367
+ import fs88 from "fs";
58258
58368
  import path100 from "path";
58259
58369
  var ROOT_MARKERS = [
58260
58370
  ".git",
@@ -58271,10 +58381,10 @@ var ROOT_MARKERS = [
58271
58381
  var SKIP_DIRS2 = /* @__PURE__ */ new Set([".git", "node_modules", "vendor", ".svn", "__pycache__", ".tox"]);
58272
58382
  function discoverChildProjects(parentDir) {
58273
58383
  const absParent = path100.resolve(parentDir);
58274
- if (!fs87.existsSync(absParent)) return [];
58384
+ if (!fs88.existsSync(absParent)) return [];
58275
58385
  let entries;
58276
58386
  try {
58277
- entries = fs87.readdirSync(absParent, { withFileTypes: true });
58387
+ entries = fs88.readdirSync(absParent, { withFileTypes: true });
58278
58388
  } catch {
58279
58389
  return [];
58280
58390
  }
@@ -58285,7 +58395,7 @@ function discoverChildProjects(parentDir) {
58285
58395
  if (SKIP_DIRS2.has(entry.name)) continue;
58286
58396
  const childDir = path100.join(absParent, entry.name);
58287
58397
  for (const marker of ROOT_MARKERS) {
58288
- if (fs87.existsSync(path100.join(childDir, marker))) {
58398
+ if (fs88.existsSync(path100.join(childDir, marker))) {
58289
58399
  children.push(childDir);
58290
58400
  break;
58291
58401
  }
@@ -58297,7 +58407,7 @@ function findProjectRoot(from) {
58297
58407
  let dir = path100.resolve(from ?? process.cwd());
58298
58408
  while (true) {
58299
58409
  for (const marker of ROOT_MARKERS) {
58300
- if (fs87.existsSync(path100.join(dir, marker))) {
58410
+ if (fs88.existsSync(path100.join(dir, marker))) {
58301
58411
  return dir;
58302
58412
  }
58303
58413
  }
@@ -58544,15 +58654,15 @@ function generateConfig(detection) {
58544
58654
  }
58545
58655
 
58546
58656
  // src/registry.ts
58547
- import fs88 from "fs";
58657
+ import fs89 from "fs";
58548
58658
  import path101 from "path";
58549
58659
  function emptyRegistry() {
58550
58660
  return { version: 1, projects: {} };
58551
58661
  }
58552
58662
  function loadRegistry2() {
58553
- if (!fs88.existsSync(REGISTRY_PATH)) return emptyRegistry();
58663
+ if (!fs89.existsSync(REGISTRY_PATH)) return emptyRegistry();
58554
58664
  try {
58555
- const raw = JSON.parse(fs88.readFileSync(REGISTRY_PATH, "utf-8"));
58665
+ const raw = JSON.parse(fs89.readFileSync(REGISTRY_PATH, "utf-8"));
58556
58666
  if (raw.version === 1 && raw.projects) return raw;
58557
58667
  return emptyRegistry();
58558
58668
  } catch {
@@ -58562,8 +58672,8 @@ function loadRegistry2() {
58562
58672
  function saveRegistry(reg) {
58563
58673
  ensureGlobalDirs();
58564
58674
  const tmp = REGISTRY_PATH + ".tmp." + process.pid;
58565
- fs88.writeFileSync(tmp, JSON.stringify(reg, null, 2) + "\n");
58566
- fs88.renameSync(tmp, REGISTRY_PATH);
58675
+ fs89.writeFileSync(tmp, JSON.stringify(reg, null, 2) + "\n");
58676
+ fs89.renameSync(tmp, REGISTRY_PATH);
58567
58677
  }
58568
58678
  function registerProject(root, opts) {
58569
58679
  const absRoot = path101.resolve(root);
@@ -58621,8 +58731,17 @@ function updateLastIndexed(root) {
58621
58731
  // src/cli/init.ts
58622
58732
  var initCommand = new Command("init").description("One-time global setup: configure MCP clients, install hooks, set up CLAUDE.md").option("--yes", "Skip prompts, use recommended defaults").option("--skip-hooks", "Do not install guard hooks").option("--skip-mcp-client", "Do not configure MCP client").option("--skip-claude-md", "Do not add CLAUDE.md block").option("--mcp-client <name>", "Force MCP client: claude-code | claude-desktop | cursor | windsurf | continue").option("--force", "Overwrite existing configuration").option("--dry-run", "Show what would be done without writing files").option("--json", "Output results as JSON (implies --yes)").option("--index", "Also register and index the current project").action(async (opts) => {
58623
58733
  const nonInteractive = opts.yes || opts.json || opts.dryRun;
58734
+ let migrationStep;
58624
58735
  if (!opts.dryRun) {
58625
58736
  ensureGlobalDirs();
58737
+ const migration = migrateGlobalConfig();
58738
+ if (migration.changed) {
58739
+ migrationStep = {
58740
+ target: "~/.trace-mcp/.config.json",
58741
+ action: "updated",
58742
+ detail: `Config migrated \u2014 added: ${migration.added.join(", ")}`
58743
+ };
58744
+ }
58626
58745
  }
58627
58746
  const mcpClients = detectMcpClients();
58628
58747
  const { hasGuardHook, guardHookVersion } = detectGuardHook();
@@ -58728,6 +58847,7 @@ var initCommand = new Command("init").description("One-time global setup: config
58728
58847
  fixConflicts = true;
58729
58848
  }
58730
58849
  const steps = [];
58850
+ if (migrationStep) steps.push(migrationStep);
58731
58851
  if (!nonInteractive) {
58732
58852
  const spin = p.spinner();
58733
58853
  spin.start("Setting up trace-mcp");
@@ -58808,7 +58928,7 @@ var initCommand = new Command("init").description("One-time global setup: config
58808
58928
  const spin = !nonInteractive ? p.spinner() : null;
58809
58929
  spin?.start("Upgrading registered projects");
58810
58930
  for (const proj of existingProjects) {
58811
- if (!fs89.existsSync(proj.root)) {
58931
+ if (!fs90.existsSync(proj.root)) {
58812
58932
  steps.push({ target: proj.root, action: "skipped", detail: "Directory not found (stale)" });
58813
58933
  continue;
58814
58934
  }
@@ -58945,11 +59065,11 @@ async function registerAndIndexProject(dir, opts) {
58945
59065
  }
58946
59066
  const detection = detectProject(projectRoot);
58947
59067
  const config = generateConfig(detection);
58948
- saveProjectConfig(projectRoot, { root: config.root, include: config.include, exclude: config.exclude });
59068
+ saveProjectConfigJsonc(projectRoot, { root: config.root, include: config.include, exclude: config.exclude });
58949
59069
  const dbPath = getDbPath(projectRoot);
58950
59070
  const oldDbPath = path102.join(projectRoot, ".trace-mcp", "index.db");
58951
- if (fs89.existsSync(oldDbPath) && !fs89.existsSync(dbPath)) {
58952
- fs89.copyFileSync(oldDbPath, dbPath);
59071
+ if (fs90.existsSync(oldDbPath) && !fs90.existsSync(dbPath)) {
59072
+ fs90.copyFileSync(oldDbPath, dbPath);
58953
59073
  }
58954
59074
  const db = initializeDatabase(dbPath);
58955
59075
  db.close();
@@ -58987,12 +59107,12 @@ async function registerMultiRootProject(parentDir, childRoots, opts) {
58987
59107
  const parentPrefix = parentDir + path102.sep;
58988
59108
  for (const proj of allProjects) {
58989
59109
  if (proj.root !== parentDir && proj.root.startsWith(parentPrefix)) {
58990
- if (fs89.existsSync(proj.dbPath)) fs89.unlinkSync(proj.dbPath);
59110
+ if (fs90.existsSync(proj.dbPath)) fs90.unlinkSync(proj.dbPath);
58991
59111
  unregisterProject(proj.root);
58992
- removeProjectConfig(proj.root);
59112
+ removeProjectConfigJsonc(proj.root);
58993
59113
  }
58994
59114
  }
58995
- saveProjectConfig(parentDir, {
59115
+ saveProjectConfigJsonc(parentDir, {
58996
59116
  root: ".",
58997
59117
  include: allInclude,
58998
59118
  exclude: allExclude,
@@ -59031,7 +59151,7 @@ function shortPath3(p5) {
59031
59151
 
59032
59152
  // src/cli/upgrade.ts
59033
59153
  import { Command as Command2 } from "commander";
59034
- import fs90 from "fs";
59154
+ import fs91 from "fs";
59035
59155
  import path103 from "path";
59036
59156
  var upgradeCommand = new Command2("upgrade").description("Upgrade trace-mcp: run DB migrations, reindex with latest plugins, update hooks and CLAUDE.md").argument("[dir]", "Project directory (omit to upgrade all registered projects)").option("--skip-hooks", "Do not update guard hooks").option("--skip-reindex", "Do not trigger reindex").option("--skip-claude-md", "Do not update CLAUDE.md block").option("--dry-run", "Show what would be done without writing files").option("--json", "Output results as JSON").action(async (dir, opts) => {
59037
59157
  const projectRoots = [];
@@ -59044,7 +59164,7 @@ var upgradeCommand = new Command2("upgrade").description("Upgrade trace-mcp: run
59044
59164
  process.exit(1);
59045
59165
  }
59046
59166
  for (const p5 of projects) {
59047
- if (fs90.existsSync(p5.root)) {
59167
+ if (fs91.existsSync(p5.root)) {
59048
59168
  projectRoots.push(p5.root);
59049
59169
  } else {
59050
59170
  logger.warn({ root: p5.root }, "Skipping stale project (directory not found)");
@@ -59138,7 +59258,7 @@ var upgradeCommand = new Command2("upgrade").description("Upgrade trace-mcp: run
59138
59258
 
59139
59259
  // src/cli/add.ts
59140
59260
  import { Command as Command3 } from "commander";
59141
- import fs91 from "fs";
59261
+ import fs92 from "fs";
59142
59262
  import path104 from "path";
59143
59263
  import * as p2 from "@clack/prompts";
59144
59264
  async function runIndexing(projectRoot, opts) {
@@ -59175,7 +59295,7 @@ function formatDuration2(ms) {
59175
59295
  }
59176
59296
  var addCommand = new Command3("add").description("Register a project for indexing: detect root, create DB, add to registry").argument("[dir]", "Project directory (default: current directory)", ".").option("--force", "Re-register even if already registered").option("--no-index", "Skip indexing after registration").option("--json", "Output results as JSON").action(async (dir, opts) => {
59177
59297
  const resolvedDir = path104.resolve(dir);
59178
- if (!fs91.existsSync(resolvedDir)) {
59298
+ if (!fs92.existsSync(resolvedDir)) {
59179
59299
  console.error(`Directory does not exist: ${resolvedDir}`);
59180
59300
  process.exit(1);
59181
59301
  }
@@ -59248,12 +59368,12 @@ DB: ${shortPath4(existing.dbPath)}`, "Existing");
59248
59368
  exclude: config.exclude
59249
59369
  };
59250
59370
  ensureGlobalDirs();
59251
- saveProjectConfig(projectRoot, configForSave);
59371
+ saveProjectConfigJsonc(projectRoot, configForSave);
59252
59372
  const dbPath = getDbPath(projectRoot);
59253
59373
  const oldDbPath = path104.join(projectRoot, ".trace-mcp", "index.db");
59254
59374
  let migrated = false;
59255
- if (fs91.existsSync(oldDbPath) && !fs91.existsSync(dbPath)) {
59256
- fs91.copyFileSync(oldDbPath, dbPath);
59375
+ if (fs92.existsSync(oldDbPath) && !fs92.existsSync(dbPath)) {
59376
+ fs92.copyFileSync(oldDbPath, dbPath);
59257
59377
  migrated = true;
59258
59378
  }
59259
59379
  const db = initializeDatabase(dbPath);
@@ -59359,11 +59479,11 @@ Discovered ${childRoots.length} child project(s):
59359
59479
  const cleaned = [];
59360
59480
  for (const proj of allProjects) {
59361
59481
  if (proj.root.startsWith(parentDir + path104.sep) || proj.root.startsWith(parentDir + "/")) {
59362
- if (fs91.existsSync(proj.dbPath)) {
59363
- fs91.unlinkSync(proj.dbPath);
59482
+ if (fs92.existsSync(proj.dbPath)) {
59483
+ fs92.unlinkSync(proj.dbPath);
59364
59484
  }
59365
59485
  unregisterProject(proj.root);
59366
- removeProjectConfig(proj.root);
59486
+ removeProjectConfigJsonc(proj.root);
59367
59487
  cleaned.push(path104.basename(proj.root));
59368
59488
  }
59369
59489
  }
@@ -59377,7 +59497,7 @@ Discovered ${childRoots.length} child project(s):
59377
59497
  exclude: mergedExclude,
59378
59498
  children: childRoots
59379
59499
  };
59380
- saveProjectConfig(parentDir, configForSave);
59500
+ saveProjectConfigJsonc(parentDir, configForSave);
59381
59501
  const dbPath = getDbPath(parentDir);
59382
59502
  const db = initializeDatabase(dbPath);
59383
59503
  db.close();
@@ -59574,7 +59694,7 @@ function shortPath5(p5) {
59574
59694
  import { Command as Command5 } from "commander";
59575
59695
  import { execFileSync as execFileSync7 } from "child_process";
59576
59696
  import path105 from "path";
59577
- import fs92 from "fs";
59697
+ import fs93 from "fs";
59578
59698
 
59579
59699
  // src/ci/report-generator.ts
59580
59700
  init_graph_analysis();
@@ -59985,15 +60105,15 @@ function writeOutput(outputPath, content) {
59985
60105
  process.stdout.write(content + "\n");
59986
60106
  } else {
59987
60107
  const resolved = path105.resolve(outputPath);
59988
- fs92.mkdirSync(path105.dirname(resolved), { recursive: true });
59989
- fs92.writeFileSync(resolved, content, "utf-8");
60108
+ fs93.mkdirSync(path105.dirname(resolved), { recursive: true });
60109
+ fs93.writeFileSync(resolved, content, "utf-8");
59990
60110
  logger.info({ path: resolved }, "CI report written");
59991
60111
  }
59992
60112
  }
59993
60113
 
59994
60114
  // src/cli/check.ts
59995
60115
  import { Command as Command6 } from "commander";
59996
- import fs93 from "fs";
60116
+ import fs94 from "fs";
59997
60117
  function resolveDbPath2(projectRoot) {
59998
60118
  const entry = getProject(projectRoot);
59999
60119
  if (entry) return entry.dbPath;
@@ -60017,7 +60137,7 @@ var checkCommand = new Command6("check").description("Run quality gate checks ag
60017
60137
  let gatesConfig;
60018
60138
  if (opts.config) {
60019
60139
  try {
60020
- const raw = JSON.parse(fs93.readFileSync(opts.config, "utf-8"));
60140
+ const raw = JSON.parse(fs94.readFileSync(opts.config, "utf-8"));
60021
60141
  const parsed = QualityGatesConfigSchema2.safeParse(raw.quality_gates ?? raw);
60022
60142
  if (!parsed.success) {
60023
60143
  console.error(`Invalid quality gates config: ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
@@ -60540,7 +60660,7 @@ analyticsCommand.command("trends").description("Show daily usage trends: tokens,
60540
60660
 
60541
60661
  // src/cli/remove.ts
60542
60662
  import { Command as Command10 } from "commander";
60543
- import fs94 from "fs";
60663
+ import fs95 from "fs";
60544
60664
  import path106 from "path";
60545
60665
  import * as p4 from "@clack/prompts";
60546
60666
  var removeCommand = new Command10("remove").description("Unregister a project and delete its index").argument("[dir]", "Project directory (default: current directory)", ".").option("--force", "Remove without confirmation").option("--keep-db", "Keep the database file (only unregister)").option("--json", "Output results as JSON").action(async (dir, opts) => {
@@ -60590,11 +60710,11 @@ var removeCommand = new Command10("remove").description("Unregister a project an
60590
60710
  }
60591
60711
  }
60592
60712
  let dbDeleted = false;
60593
- if (!opts.keepDb && fs94.existsSync(entry.dbPath)) {
60594
- fs94.unlinkSync(entry.dbPath);
60713
+ if (!opts.keepDb && fs95.existsSync(entry.dbPath)) {
60714
+ fs95.unlinkSync(entry.dbPath);
60595
60715
  dbDeleted = true;
60596
60716
  }
60597
- removeProjectConfig(entry.root);
60717
+ removeProjectConfigJsonc(entry.root);
60598
60718
  unregisterProject(entry.root);
60599
60719
  if (opts.json) {
60600
60720
  console.log(JSON.stringify({
@@ -60640,10 +60760,10 @@ Child to exclude: ${path106.basename(childRoot)}`,
60640
60760
  const currentChildren = parent.children ?? [];
60641
60761
  const newChildren = currentChildren.filter((c) => path106.resolve(c) !== path106.resolve(childRoot));
60642
60762
  if (newChildren.length === 0) {
60643
- if (!opts.keepDb && fs94.existsSync(parent.dbPath)) {
60644
- fs94.unlinkSync(parent.dbPath);
60763
+ if (!opts.keepDb && fs95.existsSync(parent.dbPath)) {
60764
+ fs95.unlinkSync(parent.dbPath);
60645
60765
  }
60646
- removeProjectConfig(parent.root);
60766
+ removeProjectConfigJsonc(parent.root);
60647
60767
  unregisterProject(parent.root);
60648
60768
  if (opts.json) {
60649
60769
  console.log(JSON.stringify({
@@ -60659,10 +60779,10 @@ Child to exclude: ${path106.basename(childRoot)}`,
60659
60779
  }
60660
60780
  if (newChildren.length === 1) {
60661
60781
  const remainingChild = newChildren[0];
60662
- if (!opts.keepDb && fs94.existsSync(parent.dbPath)) {
60663
- fs94.unlinkSync(parent.dbPath);
60782
+ if (!opts.keepDb && fs95.existsSync(parent.dbPath)) {
60783
+ fs95.unlinkSync(parent.dbPath);
60664
60784
  }
60665
- removeProjectConfig(parent.root);
60785
+ removeProjectConfigJsonc(parent.root);
60666
60786
  unregisterProject(parent.root);
60667
60787
  if (opts.json) {
60668
60788
  console.log(JSON.stringify({
@@ -60682,10 +60802,10 @@ Multi-root removed. Run \`trace-mcp add ${remainingChild}\` to re-register indiv
60682
60802
  }
60683
60803
  return;
60684
60804
  }
60685
- if (!opts.keepDb && fs94.existsSync(parent.dbPath)) {
60686
- fs94.unlinkSync(parent.dbPath);
60805
+ if (!opts.keepDb && fs95.existsSync(parent.dbPath)) {
60806
+ fs95.unlinkSync(parent.dbPath);
60687
60807
  }
60688
- removeProjectConfig(parent.root);
60808
+ removeProjectConfigJsonc(parent.root);
60689
60809
  unregisterProject(parent.root);
60690
60810
  if (opts.json) {
60691
60811
  console.log(JSON.stringify({
@@ -60712,7 +60832,7 @@ function shortPath6(p5) {
60712
60832
 
60713
60833
  // src/cli/status.ts
60714
60834
  import { Command as Command11 } from "commander";
60715
- import fs95 from "fs";
60835
+ import fs96 from "fs";
60716
60836
  import Database7 from "better-sqlite3";
60717
60837
  function resolveDbPath5(projectRoot) {
60718
60838
  const entry = getProject(projectRoot);
@@ -60757,7 +60877,7 @@ var statusCommand = new Command11("status").description("Show indexing progress
60757
60877
  projectRoot = process.cwd();
60758
60878
  }
60759
60879
  const dbPath = resolveDbPath5(projectRoot);
60760
- if (!fs95.existsSync(dbPath)) {
60880
+ if (!fs96.existsSync(dbPath)) {
60761
60881
  console.log(`No index found for ${projectRoot}`);
60762
60882
  console.log("Run `trace-mcp serve` or `trace-mcp index` first.");
60763
60883
  process.exit(1);
@@ -60795,7 +60915,7 @@ trace-mcp status \u2014 ${projectRoot}
60795
60915
  });
60796
60916
 
60797
60917
  // src/cli.ts
60798
- var PKG_VERSION2 = true ? "1.7.0" : "0.0.0-dev";
60918
+ var PKG_VERSION2 = true ? "1.8.0" : "0.0.0-dev";
60799
60919
  function registerDefaultPlugins(registry) {
60800
60920
  for (const p5 of createAllLanguagePlugins()) registry.registerLanguagePlugin(p5);
60801
60921
  for (const p5 of createAllIntegrationPlugins()) registry.registerFrameworkPlugin(p5);
@@ -61082,7 +61202,7 @@ program.command("serve-http").description("Start MCP server (HTTP/SSE transport)
61082
61202
  });
61083
61203
  program.command("index").description("Index a project directory").argument("<dir>", "Directory to index").option("-f, --force", "Force reindex all files").action(async (dir, opts) => {
61084
61204
  const resolvedDir = path107.resolve(dir);
61085
- if (!fs96.existsSync(resolvedDir)) {
61205
+ if (!fs97.existsSync(resolvedDir)) {
61086
61206
  logger.error({ dir: resolvedDir }, "Directory does not exist");
61087
61207
  process.exit(1);
61088
61208
  }
@@ -61107,7 +61227,7 @@ program.command("index").description("Index a project directory").argument("<dir
61107
61227
  });
61108
61228
  program.command("index-file").description("Incrementally reindex a single file (called by the PostToolUse auto-reindex hook)").argument("<file>", "Absolute or relative path to the file to reindex").action(async (file) => {
61109
61229
  const resolvedFile = path107.resolve(file);
61110
- if (!fs96.existsSync(resolvedFile)) {
61230
+ if (!fs97.existsSync(resolvedFile)) {
61111
61231
  process.exit(0);
61112
61232
  }
61113
61233
  let projectRoot;
@@ -61149,7 +61269,7 @@ program.command("list").description("List all registered projects").option("--js
61149
61269
  console.log("Registered projects:\n");
61150
61270
  for (const p5 of projects) {
61151
61271
  const lastIdx = p5.lastIndexed ? new Date(p5.lastIndexed).toLocaleString() : "never";
61152
- const dbExists = fs96.existsSync(p5.dbPath) ? "ok" : "missing";
61272
+ const dbExists = fs97.existsSync(p5.dbPath) ? "ok" : "missing";
61153
61273
  console.log(` ${p5.name}`);
61154
61274
  console.log(` Root: ${p5.root}`);
61155
61275
  console.log(` DB: ${dbExists}`);