@wrongstack/tools 0.307.0 → 0.307.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/patch.js CHANGED
@@ -4427,10 +4427,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
4427
4427
  }
4428
4428
  return { fileNodes, symToFile, fileStats, ensureFileNode };
4429
4429
  }
4430
- function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4430
+ function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
4431
+ const local = new Set(
4432
+ [...typeof localFiles === "string" ? [localFiles] : localFiles].map(
4433
+ (file) => file.replace(/\\/g, "/")
4434
+ )
4435
+ );
4436
+ const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
4431
4437
  return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
4432
- const aExternal = a.file === fileFilter ? 0 : 1;
4433
- const bExternal = b.file === fileFilter ? 0 : 1;
4438
+ const aExternal = isLocal(a.file) ? 0 : 1;
4439
+ const bExternal = isLocal(b.file) ? 0 : 1;
4434
4440
  return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
4435
4441
  }).map((s) => ({
4436
4442
  id: `sym:${s.id}`,
@@ -4444,7 +4450,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4444
4450
  line: s.line,
4445
4451
  signature: s.signature,
4446
4452
  scope: s.scope,
4447
- external: s.file !== fileFilter
4453
+ external: !isLocal(s.file)
4448
4454
  }));
4449
4455
  }
4450
4456
  function addWeightedEdge(edgeMap, source, target, callType, weight) {
@@ -4479,6 +4485,52 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
4479
4485
  return edges;
4480
4486
  }
4481
4487
 
4488
+ // src/codebase-index/writer-helpers.ts
4489
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
4490
+ function escapeLike(value) {
4491
+ return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4492
+ }
4493
+ function posixIndexPath(file) {
4494
+ return file.replace(/\\/g, "/").replace(/^\.\//, "");
4495
+ }
4496
+ function indexedFileMatchSql(column = "file") {
4497
+ return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
4498
+ }
4499
+ function indexedFileMatchArgs(file) {
4500
+ const posix4 = posixIndexPath(file.trim());
4501
+ return [file, posix4, `%/${escapeLike(posix4)}`];
4502
+ }
4503
+ function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
4504
+ if (packageLabel === filter) return true;
4505
+ const posixFile = posixIndexPath(storedFile);
4506
+ const posixFilter = posixIndexPath(filter.trim());
4507
+ if (!posixFilter) return false;
4508
+ return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
4509
+ }
4510
+ function assignRefsToSymbols(refs, symbols) {
4511
+ if (refs.length === 0 || symbols.length === 0) return [];
4512
+ const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4513
+ const seen = /* @__PURE__ */ new Set();
4514
+ const assigned = [];
4515
+ for (const ref of refs) {
4516
+ let owner;
4517
+ for (const symbol of ordered) {
4518
+ if (symbol.line > ref.line) break;
4519
+ owner = symbol;
4520
+ }
4521
+ if (!owner && ref.callType === "import") owner = ordered[0];
4522
+ if (!owner || owner.id <= 0) continue;
4523
+ const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
4524
+ if (seen.has(key)) continue;
4525
+ seen.add(key);
4526
+ assigned.push({ ...ref, fromId: owner.id });
4527
+ }
4528
+ return assigned;
4529
+ }
4530
+ function resolveIndexDir(projectRoot, override) {
4531
+ return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
4532
+ }
4533
+
4482
4534
  // src/codebase-index/writer-ref-mapper.ts
4483
4535
  function mapWriterRefRow(row) {
4484
4536
  return {
@@ -4534,10 +4586,23 @@ function mapCallSiteRow(row) {
4534
4586
  line: row.ref_line
4535
4587
  };
4536
4588
  }
4589
+ function resolveIndexedFiles(stmt, file) {
4590
+ const rows = stmt(
4591
+ `SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
4592
+ ).all(...indexedFileMatchArgs(file));
4593
+ return rows.map((row) => row.file);
4594
+ }
4537
4595
  function resolveSymbolIds(stmt, symbolName, file) {
4538
- const baseSql = file ? `SELECT id FROM symbols WHERE name = ? AND file = ? ORDER BY id` : `SELECT id FROM symbols WHERE name = ? ORDER BY id`;
4539
- const args = file ? [symbolName, file] : [symbolName];
4540
- const rows = stmt(baseSql).all(...args);
4596
+ if (!file) {
4597
+ const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
4598
+ return rows2.map((r) => r.id);
4599
+ }
4600
+ const indexedFiles = resolveIndexedFiles(stmt, file);
4601
+ if (indexedFiles.length === 0) return [];
4602
+ const placeholders = indexedFiles.map(() => "?").join(",");
4603
+ const rows = stmt(
4604
+ `SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
4605
+ ).all(symbolName, ...indexedFiles);
4541
4606
  return rows.map((r) => r.id);
4542
4607
  }
4543
4608
  function findIncomingCallsByName(stmt, symbolName, file, limit) {
@@ -4859,7 +4924,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
4859
4924
  const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
4860
4925
  const packageOf = readPackageLabeller(stmt);
4861
4926
  const langOf = (file) => detectLang(file) ?? "other";
4862
- const pkgFilePaths = allFiles.filter((f) => packageOf(f.file) === packageFilter).map((f) => f.file);
4927
+ const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
4863
4928
  const localFiles = new Set(pkgFilePaths);
4864
4929
  if (localFiles.size === 0) return { nodes: [], edges: [] };
4865
4930
  const filePlaceholders = [...localFiles].map(() => "?").join(",");
@@ -4935,9 +5000,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
4935
5000
  return { nodes: [...fileNodes.values()], edges };
4936
5001
  }
4937
5002
  function getSymbolGraphWithStatement(stmt, fileFilter) {
5003
+ const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
5004
+ if (indexedFiles.length === 0) return { nodes: [], edges: [] };
5005
+ const filePlaceholders = indexedFiles.map(() => "?").join(",");
4938
5006
  const syms = stmt(
4939
- "SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file = ? ORDER BY line, id"
4940
- ).all(fileFilter);
5007
+ `SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
5008
+ ).all(...indexedFiles);
4941
5009
  if (syms.length === 0) return { nodes: [], edges: [] };
4942
5010
  const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
4943
5011
  const relatedIds = new Set(syms.map((symbol) => symbol.id));
@@ -4947,16 +5015,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
4947
5015
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
4948
5016
  FROM refs r
4949
5017
  JOIN symbols s ON s.id = r.from_id
4950
- WHERE s.file = ?
5018
+ WHERE s.file IN (${filePlaceholders})
4951
5019
  UNION
4952
5020
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
4953
5021
  FROM refs r
4954
5022
  JOIN symbols s ON s.id = r.to_id
4955
- WHERE s.file = ?
5023
+ WHERE s.file IN (${filePlaceholders})
4956
5024
  )
4957
5025
  WHERE to_id IS NOT NULL
4958
5026
  GROUP BY from_id, to_id, call_type`
4959
- ).all(fileFilter, fileFilter);
5027
+ ).all(...indexedFiles, ...indexedFiles);
4960
5028
  const edgeMap = /* @__PURE__ */ new Map();
4961
5029
  for (const r of refRows) {
4962
5030
  if (r.to_id == null) continue;
@@ -4975,39 +5043,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
4975
5043
  ).all(...missingIds);
4976
5044
  for (const s of extras) symById.set(s.id, s);
4977
5045
  }
4978
- const nodes = buildSymbolGraphNodes(symById, relatedIds, fileFilter, readPackageLabeller(stmt));
5046
+ const nodes = buildSymbolGraphNodes(
5047
+ symById,
5048
+ relatedIds,
5049
+ new Set(syms.map((symbol) => symbol.file)),
5050
+ readPackageLabeller(stmt)
5051
+ );
4979
5052
  return { nodes, edges };
4980
5053
  }
4981
5054
 
4982
- // src/codebase-index/writer-helpers.ts
4983
- import { resolveWstackPaths } from "@wrongstack/core/utils";
4984
- function escapeLike(value) {
4985
- return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4986
- }
4987
- function assignRefsToSymbols(refs, symbols) {
4988
- if (refs.length === 0 || symbols.length === 0) return [];
4989
- const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4990
- const seen = /* @__PURE__ */ new Set();
4991
- const assigned = [];
4992
- for (const ref of refs) {
4993
- let owner;
4994
- for (const symbol of ordered) {
4995
- if (symbol.line > ref.line) break;
4996
- owner = symbol;
4997
- }
4998
- if (!owner && ref.callType === "import") owner = ordered[0];
4999
- if (!owner || owner.id <= 0) continue;
5000
- const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
5001
- if (seen.has(key)) continue;
5002
- seen.add(key);
5003
- assigned.push({ ...ref, fromId: owner.id });
5004
- }
5005
- return assigned;
5006
- }
5007
- function resolveIndexDir(projectRoot, override) {
5008
- return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
5009
- }
5010
-
5011
5055
  // src/codebase-index/vector-search.ts
5012
5056
  var RRF_K = 60;
5013
5057
  var VECTOR_DIMENSIONS = 384;
package/dist/read.js CHANGED
@@ -4426,10 +4426,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
4426
4426
  }
4427
4427
  return { fileNodes, symToFile, fileStats, ensureFileNode };
4428
4428
  }
4429
- function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4429
+ function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
4430
+ const local = new Set(
4431
+ [...typeof localFiles === "string" ? [localFiles] : localFiles].map(
4432
+ (file) => file.replace(/\\/g, "/")
4433
+ )
4434
+ );
4435
+ const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
4430
4436
  return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
4431
- const aExternal = a.file === fileFilter ? 0 : 1;
4432
- const bExternal = b.file === fileFilter ? 0 : 1;
4437
+ const aExternal = isLocal(a.file) ? 0 : 1;
4438
+ const bExternal = isLocal(b.file) ? 0 : 1;
4433
4439
  return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
4434
4440
  }).map((s) => ({
4435
4441
  id: `sym:${s.id}`,
@@ -4443,7 +4449,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4443
4449
  line: s.line,
4444
4450
  signature: s.signature,
4445
4451
  scope: s.scope,
4446
- external: s.file !== fileFilter
4452
+ external: !isLocal(s.file)
4447
4453
  }));
4448
4454
  }
4449
4455
  function addWeightedEdge(edgeMap, source, target, callType, weight) {
@@ -4478,6 +4484,56 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
4478
4484
  return edges;
4479
4485
  }
4480
4486
 
4487
+ // src/codebase-index/writer-helpers.ts
4488
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
4489
+ function escapeLike(value) {
4490
+ return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4491
+ }
4492
+ function posixIndexPath(file) {
4493
+ return file.replace(/\\/g, "/").replace(/^\.\//, "");
4494
+ }
4495
+ function indexedFileMatchSql(column = "file") {
4496
+ return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
4497
+ }
4498
+ function indexedFileMatchArgs(file) {
4499
+ const posix4 = posixIndexPath(file.trim());
4500
+ return [file, posix4, `%/${escapeLike(posix4)}`];
4501
+ }
4502
+ function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
4503
+ if (packageLabel === filter) return true;
4504
+ const posixFile = posixIndexPath(storedFile);
4505
+ const posixFilter = posixIndexPath(filter.trim());
4506
+ if (!posixFilter) return false;
4507
+ return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
4508
+ }
4509
+ function assignRefsToSymbols(refs, symbols) {
4510
+ if (refs.length === 0 || symbols.length === 0) return [];
4511
+ const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4512
+ const seen = /* @__PURE__ */ new Set();
4513
+ const assigned = [];
4514
+ for (const ref of refs) {
4515
+ let owner;
4516
+ for (const symbol of ordered) {
4517
+ if (symbol.line > ref.line) break;
4518
+ owner = symbol;
4519
+ }
4520
+ if (!owner && ref.callType === "import") owner = ordered[0];
4521
+ if (!owner || owner.id <= 0) continue;
4522
+ const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
4523
+ if (seen.has(key)) continue;
4524
+ seen.add(key);
4525
+ assigned.push({ ...ref, fromId: owner.id });
4526
+ }
4527
+ return assigned;
4528
+ }
4529
+ function resolveIndexDir(projectRoot, override) {
4530
+ return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
4531
+ }
4532
+ function codebaseIndexDirOverride(ctx) {
4533
+ const v = ctx.meta?.["codebaseIndexDir"];
4534
+ return typeof v === "string" ? v : void 0;
4535
+ }
4536
+
4481
4537
  // src/codebase-index/writer-ref-mapper.ts
4482
4538
  function mapWriterRefRow(row) {
4483
4539
  return {
@@ -4533,10 +4589,23 @@ function mapCallSiteRow(row) {
4533
4589
  line: row.ref_line
4534
4590
  };
4535
4591
  }
4592
+ function resolveIndexedFiles(stmt, file) {
4593
+ const rows = stmt(
4594
+ `SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
4595
+ ).all(...indexedFileMatchArgs(file));
4596
+ return rows.map((row) => row.file);
4597
+ }
4536
4598
  function resolveSymbolIds(stmt, symbolName, file) {
4537
- const baseSql = file ? `SELECT id FROM symbols WHERE name = ? AND file = ? ORDER BY id` : `SELECT id FROM symbols WHERE name = ? ORDER BY id`;
4538
- const args = file ? [symbolName, file] : [symbolName];
4539
- const rows = stmt(baseSql).all(...args);
4599
+ if (!file) {
4600
+ const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
4601
+ return rows2.map((r) => r.id);
4602
+ }
4603
+ const indexedFiles = resolveIndexedFiles(stmt, file);
4604
+ if (indexedFiles.length === 0) return [];
4605
+ const placeholders = indexedFiles.map(() => "?").join(",");
4606
+ const rows = stmt(
4607
+ `SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
4608
+ ).all(symbolName, ...indexedFiles);
4540
4609
  return rows.map((r) => r.id);
4541
4610
  }
4542
4611
  function findIncomingCallsByName(stmt, symbolName, file, limit) {
@@ -4858,7 +4927,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
4858
4927
  const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
4859
4928
  const packageOf = readPackageLabeller(stmt);
4860
4929
  const langOf = (file) => detectLang(file) ?? "other";
4861
- const pkgFilePaths = allFiles.filter((f) => packageOf(f.file) === packageFilter).map((f) => f.file);
4930
+ const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
4862
4931
  const localFiles = new Set(pkgFilePaths);
4863
4932
  if (localFiles.size === 0) return { nodes: [], edges: [] };
4864
4933
  const filePlaceholders = [...localFiles].map(() => "?").join(",");
@@ -4934,9 +5003,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
4934
5003
  return { nodes: [...fileNodes.values()], edges };
4935
5004
  }
4936
5005
  function getSymbolGraphWithStatement(stmt, fileFilter) {
5006
+ const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
5007
+ if (indexedFiles.length === 0) return { nodes: [], edges: [] };
5008
+ const filePlaceholders = indexedFiles.map(() => "?").join(",");
4937
5009
  const syms = stmt(
4938
- "SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file = ? ORDER BY line, id"
4939
- ).all(fileFilter);
5010
+ `SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
5011
+ ).all(...indexedFiles);
4940
5012
  if (syms.length === 0) return { nodes: [], edges: [] };
4941
5013
  const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
4942
5014
  const relatedIds = new Set(syms.map((symbol) => symbol.id));
@@ -4946,16 +5018,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
4946
5018
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
4947
5019
  FROM refs r
4948
5020
  JOIN symbols s ON s.id = r.from_id
4949
- WHERE s.file = ?
5021
+ WHERE s.file IN (${filePlaceholders})
4950
5022
  UNION
4951
5023
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
4952
5024
  FROM refs r
4953
5025
  JOIN symbols s ON s.id = r.to_id
4954
- WHERE s.file = ?
5026
+ WHERE s.file IN (${filePlaceholders})
4955
5027
  )
4956
5028
  WHERE to_id IS NOT NULL
4957
5029
  GROUP BY from_id, to_id, call_type`
4958
- ).all(fileFilter, fileFilter);
5030
+ ).all(...indexedFiles, ...indexedFiles);
4959
5031
  const edgeMap = /* @__PURE__ */ new Map();
4960
5032
  for (const r of refRows) {
4961
5033
  if (r.to_id == null) continue;
@@ -4974,43 +5046,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
4974
5046
  ).all(...missingIds);
4975
5047
  for (const s of extras) symById.set(s.id, s);
4976
5048
  }
4977
- const nodes = buildSymbolGraphNodes(symById, relatedIds, fileFilter, readPackageLabeller(stmt));
5049
+ const nodes = buildSymbolGraphNodes(
5050
+ symById,
5051
+ relatedIds,
5052
+ new Set(syms.map((symbol) => symbol.file)),
5053
+ readPackageLabeller(stmt)
5054
+ );
4978
5055
  return { nodes, edges };
4979
5056
  }
4980
5057
 
4981
- // src/codebase-index/writer-helpers.ts
4982
- import { resolveWstackPaths } from "@wrongstack/core/utils";
4983
- function escapeLike(value) {
4984
- return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4985
- }
4986
- function assignRefsToSymbols(refs, symbols) {
4987
- if (refs.length === 0 || symbols.length === 0) return [];
4988
- const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4989
- const seen = /* @__PURE__ */ new Set();
4990
- const assigned = [];
4991
- for (const ref of refs) {
4992
- let owner;
4993
- for (const symbol of ordered) {
4994
- if (symbol.line > ref.line) break;
4995
- owner = symbol;
4996
- }
4997
- if (!owner && ref.callType === "import") owner = ordered[0];
4998
- if (!owner || owner.id <= 0) continue;
4999
- const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
5000
- if (seen.has(key)) continue;
5001
- seen.add(key);
5002
- assigned.push({ ...ref, fromId: owner.id });
5003
- }
5004
- return assigned;
5005
- }
5006
- function resolveIndexDir(projectRoot, override) {
5007
- return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
5008
- }
5009
- function codebaseIndexDirOverride(ctx) {
5010
- const v = ctx.meta?.["codebaseIndexDir"];
5011
- return typeof v === "string" ? v : void 0;
5012
- }
5013
-
5014
5058
  // src/codebase-index/vector-search.ts
5015
5059
  var RRF_K = 60;
5016
5060
  var VECTOR_DIMENSIONS = 384;
package/dist/replace.js CHANGED
@@ -4592,10 +4592,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
4592
4592
  }
4593
4593
  return { fileNodes, symToFile, fileStats, ensureFileNode };
4594
4594
  }
4595
- function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4595
+ function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
4596
+ const local = new Set(
4597
+ [...typeof localFiles === "string" ? [localFiles] : localFiles].map(
4598
+ (file) => file.replace(/\\/g, "/")
4599
+ )
4600
+ );
4601
+ const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
4596
4602
  return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
4597
- const aExternal = a.file === fileFilter ? 0 : 1;
4598
- const bExternal = b.file === fileFilter ? 0 : 1;
4603
+ const aExternal = isLocal(a.file) ? 0 : 1;
4604
+ const bExternal = isLocal(b.file) ? 0 : 1;
4599
4605
  return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
4600
4606
  }).map((s) => ({
4601
4607
  id: `sym:${s.id}`,
@@ -4609,7 +4615,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4609
4615
  line: s.line,
4610
4616
  signature: s.signature,
4611
4617
  scope: s.scope,
4612
- external: s.file !== fileFilter
4618
+ external: !isLocal(s.file)
4613
4619
  }));
4614
4620
  }
4615
4621
  function addWeightedEdge(edgeMap, source, target, callType, weight) {
@@ -4644,6 +4650,52 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
4644
4650
  return edges;
4645
4651
  }
4646
4652
 
4653
+ // src/codebase-index/writer-helpers.ts
4654
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
4655
+ function escapeLike(value) {
4656
+ return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4657
+ }
4658
+ function posixIndexPath(file) {
4659
+ return file.replace(/\\/g, "/").replace(/^\.\//, "");
4660
+ }
4661
+ function indexedFileMatchSql(column = "file") {
4662
+ return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
4663
+ }
4664
+ function indexedFileMatchArgs(file) {
4665
+ const posix4 = posixIndexPath(file.trim());
4666
+ return [file, posix4, `%/${escapeLike(posix4)}`];
4667
+ }
4668
+ function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
4669
+ if (packageLabel === filter) return true;
4670
+ const posixFile = posixIndexPath(storedFile);
4671
+ const posixFilter = posixIndexPath(filter.trim());
4672
+ if (!posixFilter) return false;
4673
+ return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
4674
+ }
4675
+ function assignRefsToSymbols(refs, symbols) {
4676
+ if (refs.length === 0 || symbols.length === 0) return [];
4677
+ const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4678
+ const seen = /* @__PURE__ */ new Set();
4679
+ const assigned = [];
4680
+ for (const ref of refs) {
4681
+ let owner;
4682
+ for (const symbol of ordered) {
4683
+ if (symbol.line > ref.line) break;
4684
+ owner = symbol;
4685
+ }
4686
+ if (!owner && ref.callType === "import") owner = ordered[0];
4687
+ if (!owner || owner.id <= 0) continue;
4688
+ const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
4689
+ if (seen.has(key)) continue;
4690
+ seen.add(key);
4691
+ assigned.push({ ...ref, fromId: owner.id });
4692
+ }
4693
+ return assigned;
4694
+ }
4695
+ function resolveIndexDir(projectRoot, override) {
4696
+ return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
4697
+ }
4698
+
4647
4699
  // src/codebase-index/writer-ref-mapper.ts
4648
4700
  function mapWriterRefRow(row) {
4649
4701
  return {
@@ -4699,10 +4751,23 @@ function mapCallSiteRow(row) {
4699
4751
  line: row.ref_line
4700
4752
  };
4701
4753
  }
4754
+ function resolveIndexedFiles(stmt, file) {
4755
+ const rows = stmt(
4756
+ `SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
4757
+ ).all(...indexedFileMatchArgs(file));
4758
+ return rows.map((row) => row.file);
4759
+ }
4702
4760
  function resolveSymbolIds(stmt, symbolName, file) {
4703
- const baseSql = file ? `SELECT id FROM symbols WHERE name = ? AND file = ? ORDER BY id` : `SELECT id FROM symbols WHERE name = ? ORDER BY id`;
4704
- const args = file ? [symbolName, file] : [symbolName];
4705
- const rows = stmt(baseSql).all(...args);
4761
+ if (!file) {
4762
+ const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
4763
+ return rows2.map((r) => r.id);
4764
+ }
4765
+ const indexedFiles = resolveIndexedFiles(stmt, file);
4766
+ if (indexedFiles.length === 0) return [];
4767
+ const placeholders = indexedFiles.map(() => "?").join(",");
4768
+ const rows = stmt(
4769
+ `SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
4770
+ ).all(symbolName, ...indexedFiles);
4706
4771
  return rows.map((r) => r.id);
4707
4772
  }
4708
4773
  function findIncomingCallsByName(stmt, symbolName, file, limit) {
@@ -5024,7 +5089,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
5024
5089
  const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
5025
5090
  const packageOf = readPackageLabeller(stmt);
5026
5091
  const langOf = (file) => detectLang(file) ?? "other";
5027
- const pkgFilePaths = allFiles.filter((f) => packageOf(f.file) === packageFilter).map((f) => f.file);
5092
+ const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
5028
5093
  const localFiles = new Set(pkgFilePaths);
5029
5094
  if (localFiles.size === 0) return { nodes: [], edges: [] };
5030
5095
  const filePlaceholders = [...localFiles].map(() => "?").join(",");
@@ -5100,9 +5165,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
5100
5165
  return { nodes: [...fileNodes.values()], edges };
5101
5166
  }
5102
5167
  function getSymbolGraphWithStatement(stmt, fileFilter) {
5168
+ const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
5169
+ if (indexedFiles.length === 0) return { nodes: [], edges: [] };
5170
+ const filePlaceholders = indexedFiles.map(() => "?").join(",");
5103
5171
  const syms = stmt(
5104
- "SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file = ? ORDER BY line, id"
5105
- ).all(fileFilter);
5172
+ `SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
5173
+ ).all(...indexedFiles);
5106
5174
  if (syms.length === 0) return { nodes: [], edges: [] };
5107
5175
  const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
5108
5176
  const relatedIds = new Set(syms.map((symbol) => symbol.id));
@@ -5112,16 +5180,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
5112
5180
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
5113
5181
  FROM refs r
5114
5182
  JOIN symbols s ON s.id = r.from_id
5115
- WHERE s.file = ?
5183
+ WHERE s.file IN (${filePlaceholders})
5116
5184
  UNION
5117
5185
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
5118
5186
  FROM refs r
5119
5187
  JOIN symbols s ON s.id = r.to_id
5120
- WHERE s.file = ?
5188
+ WHERE s.file IN (${filePlaceholders})
5121
5189
  )
5122
5190
  WHERE to_id IS NOT NULL
5123
5191
  GROUP BY from_id, to_id, call_type`
5124
- ).all(fileFilter, fileFilter);
5192
+ ).all(...indexedFiles, ...indexedFiles);
5125
5193
  const edgeMap = /* @__PURE__ */ new Map();
5126
5194
  for (const r of refRows) {
5127
5195
  if (r.to_id == null) continue;
@@ -5140,39 +5208,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
5140
5208
  ).all(...missingIds);
5141
5209
  for (const s of extras) symById.set(s.id, s);
5142
5210
  }
5143
- const nodes = buildSymbolGraphNodes(symById, relatedIds, fileFilter, readPackageLabeller(stmt));
5211
+ const nodes = buildSymbolGraphNodes(
5212
+ symById,
5213
+ relatedIds,
5214
+ new Set(syms.map((symbol) => symbol.file)),
5215
+ readPackageLabeller(stmt)
5216
+ );
5144
5217
  return { nodes, edges };
5145
5218
  }
5146
5219
 
5147
- // src/codebase-index/writer-helpers.ts
5148
- import { resolveWstackPaths } from "@wrongstack/core/utils";
5149
- function escapeLike(value) {
5150
- return value.replace(/[\\%_]/g, (char) => `\\${char}`);
5151
- }
5152
- function assignRefsToSymbols(refs, symbols) {
5153
- if (refs.length === 0 || symbols.length === 0) return [];
5154
- const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
5155
- const seen = /* @__PURE__ */ new Set();
5156
- const assigned = [];
5157
- for (const ref of refs) {
5158
- let owner;
5159
- for (const symbol of ordered) {
5160
- if (symbol.line > ref.line) break;
5161
- owner = symbol;
5162
- }
5163
- if (!owner && ref.callType === "import") owner = ordered[0];
5164
- if (!owner || owner.id <= 0) continue;
5165
- const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
5166
- if (seen.has(key)) continue;
5167
- seen.add(key);
5168
- assigned.push({ ...ref, fromId: owner.id });
5169
- }
5170
- return assigned;
5171
- }
5172
- function resolveIndexDir(projectRoot, override) {
5173
- return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
5174
- }
5175
-
5176
5220
  // src/codebase-index/vector-search.ts
5177
5221
  var RRF_K = 60;
5178
5222
  var VECTOR_DIMENSIONS = 384;