@wrongstack/tools 0.318.0 → 0.319.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.
Files changed (82) hide show
  1. package/dist/_util.d.ts +13 -0
  2. package/dist/audit.js +4 -4
  3. package/dist/bash.js +2 -2
  4. package/dist/builtin.js +37 -37
  5. package/dist/{chunk-TKA4VEX2.js → chunk-2472NT76.js} +2 -2
  6. package/dist/{chunk-UE3UBMCP.js → chunk-4Q7LFU4T.js} +3 -3
  7. package/dist/{chunk-ZZT45EHF.js → chunk-65EMYN5G.js} +3 -3
  8. package/dist/{chunk-A6BRWIXN.js → chunk-6IEBD27U.js} +20 -5
  9. package/dist/{chunk-P7ZQ2FAJ.js → chunk-7WV3D4S3.js} +2 -2
  10. package/dist/{chunk-3U4H6ZRF.js → chunk-C3W3V54D.js} +4 -4
  11. package/dist/{chunk-AGUSOFNI.js → chunk-COUNXG4X.js} +3 -3
  12. package/dist/{chunk-VB3MJGCV.js → chunk-D4CXUZIF.js} +2 -2
  13. package/dist/{chunk-5WNDJHT6.js → chunk-DPKTXJQS.js} +2 -2
  14. package/dist/{chunk-EMRGN4KM.js → chunk-HBM4QNXU.js} +2 -2
  15. package/dist/{chunk-J5SKD6LN.js → chunk-HWDB2G7J.js} +2 -2
  16. package/dist/{chunk-ZLTFLC25.js → chunk-IIF5HIVF.js} +2 -2
  17. package/dist/{chunk-UKGMDCXT.js → chunk-KD5EHYA2.js} +2 -2
  18. package/dist/{chunk-VZLX2JZG.js → chunk-MRKWZCHZ.js} +3 -3
  19. package/dist/{chunk-S2GBLQ5S.js → chunk-MYRMD6PZ.js} +3 -3
  20. package/dist/{chunk-EOOFNYIT.js → chunk-N5O3FK5Q.js} +2 -2
  21. package/dist/{chunk-EEOFQDT6.js → chunk-OCUXN6Y3.js} +46 -2
  22. package/dist/{chunk-3QQSBUXR.js → chunk-ODFVG54U.js} +3 -3
  23. package/dist/{chunk-6GZPSWP3.js → chunk-OJ4FIBAN.js} +2 -2
  24. package/dist/{chunk-CISOLTOP.js → chunk-OYVPBPCL.js} +3 -3
  25. package/dist/{chunk-WI3VDXHD.js → chunk-PMHVSHMU.js} +40 -10
  26. package/dist/{chunk-CIFAIIHI.js → chunk-PRXZOIEW.js} +3 -3
  27. package/dist/{chunk-D33S4RQG.js → chunk-QLF74MSV.js} +7 -1
  28. package/dist/{chunk-CVALEVGA.js → chunk-QZDOQRF7.js} +3 -3
  29. package/dist/{chunk-YF3D5INN.js → chunk-RK47IWO3.js} +67 -68
  30. package/dist/{chunk-MX25MTDJ.js → chunk-SYXW3Y5Z.js} +2 -2
  31. package/dist/{chunk-BLCSYKNN.js → chunk-TFMVHYJI.js} +4 -3
  32. package/dist/{chunk-JJQB6R7Y.js → chunk-TX3R5NVV.js} +6 -6
  33. package/dist/{chunk-SOG7XIRF.js → chunk-UC3RKRIV.js} +2 -2
  34. package/dist/{chunk-ZE6KLBUO.js → chunk-UMXVT7ST.js} +2 -2
  35. package/dist/{chunk-K23JNFE3.js → chunk-VALQFAY2.js} +109 -34
  36. package/dist/{chunk-4AEZIFOW.js → chunk-VFF3Q5Z3.js} +3 -3
  37. package/dist/{chunk-6GVXZCQV.js → chunk-W4GAAI3M.js} +2 -2
  38. package/dist/{chunk-HTYEO67J.js → chunk-WNUJR3H4.js} +2 -2
  39. package/dist/{chunk-CPVLVQYT.js → chunk-Y7QXSE7N.js} +3 -3
  40. package/dist/{chunk-CPSAF2AU.js → chunk-YZHK4TLF.js} +2 -2
  41. package/dist/{chunk-MRZOVQ5D.js → chunk-Z4VBTVUM.js} +3 -3
  42. package/dist/{chunk-4E42D7UF.js → chunk-ZDUGI5BC.js} +2 -2
  43. package/dist/{chunk-WJYXMB2R.js → chunk-ZKSBHXVB.js} +3 -3
  44. package/dist/codebase-index/generic-parser.d.ts +8 -1
  45. package/dist/codebase-index/index.js +9 -9
  46. package/dist/codebase-index/parser-worker-script.js +3 -3
  47. package/dist/codebase-index/project-server.js +5 -5
  48. package/dist/codebase-index/worker.js +4 -4
  49. package/dist/codebase-index/writer-refs.d.ts +1 -1
  50. package/dist/diff.js +2 -2
  51. package/dist/document.js +2 -2
  52. package/dist/e2e.js +2 -2
  53. package/dist/edit.js +8 -8
  54. package/dist/exec.js +2 -2
  55. package/dist/fetch.js +2 -2
  56. package/dist/format.js +4 -4
  57. package/dist/{generic-parser-VUXDIAOZ.js → generic-parser-WFMIRHBX.js} +2 -2
  58. package/dist/git.js +2 -2
  59. package/dist/glob.js +2 -2
  60. package/dist/grep.js +2 -2
  61. package/dist/index.js +39 -39
  62. package/dist/install.js +4 -4
  63. package/dist/json.js +2 -2
  64. package/dist/languages/index.js +2 -2
  65. package/dist/{legacy-bridge-SFNXIRAP.js → legacy-bridge-EC7GM2IW.js} +4 -4
  66. package/dist/lint.js +4 -4
  67. package/dist/logs.js +2 -2
  68. package/dist/outdated.js +2 -2
  69. package/dist/pack.js +38 -38
  70. package/dist/{parser-dispatch-X62UWXJS.js → parser-dispatch-3PDBKIQ7.js} +4 -4
  71. package/dist/patch.js +8 -8
  72. package/dist/{py-parser-TDXSQZBC.js → py-parser-RFWG2HYI.js} +3 -3
  73. package/dist/read.js +8 -8
  74. package/dist/replace.js +8 -8
  75. package/dist/scaffold.js +2 -2
  76. package/dist/test.js +4 -4
  77. package/dist/tool-tier.js +39 -39
  78. package/dist/{tree-sitter-parser-AIERW3YI.js → tree-sitter-parser-FGKHJGSX.js} +2 -2
  79. package/dist/tree.js +2 -2
  80. package/dist/typecheck.js +4 -4
  81. package/dist/write.js +8 -8
  82. package/package.json +5 -5
@@ -20,7 +20,7 @@ import {
20
20
  COMMAND_OUTPUT_MAX_BYTES,
21
21
  normalizeCommandOutput,
22
22
  safeResolveReal
23
- } from "./chunk-D33S4RQG.js";
23
+ } from "./chunk-QLF74MSV.js";
24
24
 
25
25
  // src/exec.ts
26
26
  import { spawn } from "node:child_process";
@@ -32,13 +32,12 @@ import {
32
32
  import { toErrorMessage } from "@wrongstack/core/utils/error";
33
33
 
34
34
  // src/_danger-detect.ts
35
- var argHas = (args, value) => args.includes(value);
36
35
  var argMatches = (args, re) => args.some((a) => re.test(a));
37
36
  var flagLetters = (args) => {
38
37
  const seen = /* @__PURE__ */ new Set();
39
38
  for (const a of args) {
40
39
  if (/^-[a-zA-Z]+$/.test(a)) {
41
- for (const ch of a.slice(1)) seen.add(ch);
40
+ for (const ch of a.slice(1)) seen.add(ch.toLowerCase());
42
41
  } else if (a === "--recursive") {
43
42
  seen.add("r");
44
43
  } else if (a === "--force") {
@@ -54,13 +53,29 @@ var RULES = [
54
53
  // want to do intentionally. We downgrade it to 'destructive' so the
55
54
  // confirm prompt can approve. Short clusters, GNU long forms
56
55
  // (`--recursive --force`), and mixed shapes all classify identically.
56
+ // The Windows cmd.exe shape classifies identically too: `rmdir /s /q`
57
+ // (and its `rd` alias) is the same operation — /s is the recursive half,
58
+ // /q the quiet (no per-directory prompt, i.e. the "force") half. /s alone
59
+ // still prompts in cmd, so it stays safe, mirroring the PowerShell rule's
60
+ // requirement for both -Recurse and -Force. `del`/`erase` (erase is a cmd
61
+ // alias of del) with /s is classified as well: `del /s` deletes matching
62
+ // files in the whole subtree WITHOUT any per-file prompt, so there /s
63
+ // alone is the recursive-force half (/f only overrides read-only, /q only
64
+ // mutes the global-wildcard "are you sure"). Non-recursive del/erase
65
+ // (single files, or a quiet single-directory wildcard) stays safe.
57
66
  {
58
67
  id: "rm-recursive",
59
68
  level: "destructive",
60
69
  test: (cmd, args) => {
61
- if (cmd !== "rm" && cmd !== "rmdir") return false;
70
+ if (cmd !== "rm" && cmd !== "rmdir" && cmd !== "rd" && cmd !== "del" && cmd !== "erase") {
71
+ return false;
72
+ }
62
73
  const letters = flagLetters(args);
63
- return letters.has("r") && letters.has("f");
74
+ if (letters.has("r") && letters.has("f")) return true;
75
+ const has = (flag) => args.some((a) => a.toLowerCase() === `/${flag}`);
76
+ if (cmd === "rmdir" || cmd === "rd") return has("s") && has("q");
77
+ if (cmd === "del" || cmd === "erase") return has("s");
78
+ return false;
64
79
  },
65
80
  reason: "recursive force-delete"
66
81
  },
@@ -70,9 +85,9 @@ var RULES = [
70
85
  level: "destructive",
71
86
  test: (cmd, args) => {
72
87
  if (cmd !== "powershell" && cmd !== "pwsh") return false;
73
- const hasRecurse = argMatches(args, /^-(?:R|Recurse|Recurse\s)/);
74
- const hasForce = argHas(args, "-Force") || argHas(args, "-F");
75
- if (argHas(args, "-WhatIf")) return false;
88
+ const hasRecurse = argMatches(args, /^-(?:r|recurse)/i);
89
+ const hasForce = argMatches(args, /^-(?:f|force)$/i);
90
+ if (argMatches(args, /^-whatif$/i)) return false;
76
91
  return hasRecurse && hasForce;
77
92
  },
78
93
  reason: "Remove-Item with -Recurse -Force"
@@ -191,6 +206,15 @@ var RULES = [
191
206
  // ----- VCS history rewrite (destructive) -----
192
207
  // `git push --force` / `-f` rewrites remote history. `--force-with-lease`
193
208
  // is the safer variant (checks remote hasn't moved) but still rewrites.
209
+ // A refspec prefixed with `+` (`git push origin +main`,
210
+ // `+HEAD:refs/heads/main`) is per-refspec force — documented git shorthand
211
+ // equivalent to `--force` for that ref — so it classifies identically. A
212
+ // `+` anywhere else in a refspec (branch `feature+fix`) is just a
213
+ // character, and a leading `^` EXCLUDES the ref (with --all/--mirror);
214
+ // neither is force syntax. `--dry-run` / `-n` rewrites nothing and is
215
+ // exempt, like the PowerShell -WhatIf carve-out above (combined short
216
+ // clusters like `-nf` count as dry-run too — git push's short flags are
217
+ // only -q -v -f -n -u -o, so an 'n' in a cluster means dry-run).
194
218
  {
195
219
  id: "git-push-force",
196
220
  level: "destructive",
@@ -198,10 +222,16 @@ var RULES = [
198
222
  if (cmd !== "git") return false;
199
223
  const pushIdx = args.indexOf("push");
200
224
  if (pushIdx < 0) return false;
225
+ if (args.slice(pushIdx + 1).some((a) => a === "--dry-run" || a === "-n" || /^-[a-z]*n[a-z]*$/i.test(a))) {
226
+ return false;
227
+ }
201
228
  for (let i = pushIdx + 1; i < args.length; i++) {
202
229
  const a = args[i];
203
230
  if (a === "--force" || a === "-f" || a === "--force-with-lease") return true;
204
- if (!a.startsWith("-") && !a.includes("=")) continue;
231
+ if (!a.startsWith("-") && !a.includes("=")) {
232
+ if (a.startsWith("+")) return true;
233
+ continue;
234
+ }
205
235
  if (a.startsWith("--force")) return true;
206
236
  }
207
237
  return false;
@@ -1730,4 +1760,4 @@ export {
1730
1760
  getExecAllowlist,
1731
1761
  execTool
1732
1762
  };
1733
- //# sourceMappingURL=chunk-WI3VDXHD.js.map
1763
+ //# sourceMappingURL=chunk-PMHVSHMU.js.map
@@ -3,12 +3,12 @@ import {
3
3
  } from "./chunk-FQZOHLG3.js";
4
4
  import {
5
5
  enqueueReindex
6
- } from "./chunk-VZLX2JZG.js";
6
+ } from "./chunk-MRKWZCHZ.js";
7
7
  import {
8
8
  safeResolveReal,
9
9
  sha256hex,
10
10
  truncateDiffPayload
11
- } from "./chunk-D33S4RQG.js";
11
+ } from "./chunk-QLF74MSV.js";
12
12
 
13
13
  // src/edit.ts
14
14
  import * as fs from "node:fs/promises";
@@ -473,4 +473,4 @@ Compare this against your old_string and retry with the file's actual text.` : "
473
473
  export {
474
474
  editTool
475
475
  };
476
- //# sourceMappingURL=chunk-CIFAIIHI.js.map
476
+ //# sourceMappingURL=chunk-PRXZOIEW.js.map
@@ -107,6 +107,11 @@ async function safeResolveReal(input, ctx) {
107
107
  const abs = safeResolve(input, ctx);
108
108
  return await resolveRealInsideRoot(abs, ctx);
109
109
  }
110
+ async function safeResolveProjectPath(input, ctx) {
111
+ const root = ctx.projectRoot ?? ctx.cwd ?? process.cwd();
112
+ const abs = path.isAbsolute(input) ? input : path.resolve(root, input);
113
+ return await safeResolveReal(abs, ctx);
114
+ }
110
115
  function truncateDiffPayload(diff, maxBytes) {
111
116
  const total = Buffer.byteLength(diff, "utf8");
112
117
  if (total <= maxBytes) return { text: diff, truncated: false };
@@ -213,10 +218,11 @@ export {
213
218
  assertRealInsideRoot,
214
219
  resolveRealInsideRoot,
215
220
  safeResolveReal,
221
+ safeResolveProjectPath,
216
222
  truncateDiffPayload,
217
223
  truncateMiddle,
218
224
  isBinaryBuffer,
219
225
  COMMAND_OUTPUT_MAX_BYTES,
220
226
  normalizeCommandOutput
221
227
  };
222
- //# sourceMappingURL=chunk-D33S4RQG.js.map
228
+ //# sourceMappingURL=chunk-QLF74MSV.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  tryLegacyPackageOperation
3
- } from "./chunk-4E42D7UF.js";
3
+ } from "./chunk-ZDUGI5BC.js";
4
4
  import {
5
5
  spawnStream
6
6
  } from "./chunk-ZHH3BEWU.js";
@@ -9,7 +9,7 @@ import {
9
9
  detectPackageManager,
10
10
  normalizeCommandOutput,
11
11
  safeResolveReal
12
- } from "./chunk-D33S4RQG.js";
12
+ } from "./chunk-QLF74MSV.js";
13
13
 
14
14
  // src/audit.ts
15
15
  var SEVERITY_RANK = {
@@ -188,4 +188,4 @@ function extractAdvisories(data) {
188
188
  export {
189
189
  auditTool
190
190
  };
191
- //# sourceMappingURL=chunk-CVALEVGA.js.map
191
+ //# sourceMappingURL=chunk-QZDOQRF7.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseTreeSitterAst
3
- } from "./chunk-EEOFQDT6.js";
3
+ } from "./chunk-OCUXN6Y3.js";
4
4
  import {
5
5
  spawnStream
6
6
  } from "./chunk-ZHH3BEWU.js";
@@ -13,7 +13,7 @@ import {
13
13
  outgoingCallsService,
14
14
  runStartupIndex,
15
15
  searchCodebaseIndex
16
- } from "./chunk-VZLX2JZG.js";
16
+ } from "./chunk-MRKWZCHZ.js";
17
17
  import {
18
18
  IndexTimeoutError,
19
19
  SCHEMA_VERSION,
@@ -21,15 +21,16 @@ import {
21
21
  indexCircuitBreaker,
22
22
  indexStorePool,
23
23
  resolveIndexDir
24
- } from "./chunk-BLCSYKNN.js";
24
+ } from "./chunk-TFMVHYJI.js";
25
25
  import {
26
26
  EXT_TO_LANG,
27
27
  detectLang,
28
28
  isIndexablePath
29
29
  } from "./chunk-YOHO4DVT.js";
30
30
  import {
31
- normalizeCommandOutput
32
- } from "./chunk-D33S4RQG.js";
31
+ normalizeCommandOutput,
32
+ safeResolveProjectPath
33
+ } from "./chunk-QLF74MSV.js";
33
34
 
34
35
  // src/codebase-index/codebase-ast-replace-tool.ts
35
36
  import * as path2 from "node:path";
@@ -689,7 +690,8 @@ var codebaseAstReplaceTool = {
689
690
  async execute(input, ctx) {
690
691
  try {
691
692
  const projectRoot = ctx.projectRoot ?? ctx.cwd ?? process.cwd();
692
- const result = await replaceSymbolInFile(input, projectRoot);
693
+ const file = await safeResolveProjectPath(input.file, ctx);
694
+ const result = await replaceSymbolInFile({ ...input, file }, projectRoot);
693
695
  return {
694
696
  status: "ok",
695
697
  file: path2.relative(projectRoot, result.file).replace(/\\/g, "/"),
@@ -711,7 +713,6 @@ var codebaseAstReplaceTool = {
711
713
 
712
714
  // src/codebase-index/codebase-invariant-check-tool.ts
713
715
  import * as fs2 from "node:fs/promises";
714
- import * as path3 from "node:path";
715
716
  import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
716
717
  var codebaseInvariantCheckTool = {
717
718
  name: "codebase-invariant-check",
@@ -751,8 +752,7 @@ var codebaseInvariantCheckTool = {
751
752
  let originalCode = input.originalCode;
752
753
  let lang = input.lang;
753
754
  if (!originalCode && input.file) {
754
- const root = ctx.projectRoot ?? ctx.cwd ?? process.cwd();
755
- const resolved = path3.isAbsolute(input.file) ? input.file : path3.resolve(root, input.file);
755
+ const resolved = await safeResolveProjectPath(input.file, ctx);
756
756
  originalCode = await fs2.readFile(resolved, "utf8");
757
757
  if (!lang) {
758
758
  lang = detectLang(resolved) ?? "ts";
@@ -791,7 +791,7 @@ var codebaseInvariantCheckTool = {
791
791
  };
792
792
 
793
793
  // src/codebase-index/codebase-impact-analysis-tool.ts
794
- import * as path4 from "node:path";
794
+ import * as path3 from "node:path";
795
795
  import { toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
796
796
  var TEST_FILE_REGEX = /(?:test|spec|mock|fixture|bench)[s]?[/\\._]/i;
797
797
  var codebaseImpactAnalysisTool = {
@@ -884,7 +884,7 @@ var codebaseImpactAnalysisTool = {
884
884
  const testFilesSet = /* @__PURE__ */ new Set();
885
885
  const callSites = [];
886
886
  for (const site of rawSites) {
887
- const relPath = path4.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
887
+ const relPath = path3.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
888
888
  const isTest = TEST_FILE_REGEX.test(relPath);
889
889
  if (isTest) {
890
890
  testFilesSet.add(relPath);
@@ -1463,11 +1463,11 @@ import { toErrorMessage as toErrorMessage7 } from "@wrongstack/core/utils";
1463
1463
 
1464
1464
  // src/codebase-index/repo-map.ts
1465
1465
  import * as fs4 from "node:fs/promises";
1466
- import * as path6 from "node:path";
1466
+ import * as path5 from "node:path";
1467
1467
 
1468
1468
  // src/codebase-index/skeleton-extractor.ts
1469
1469
  import * as fs3 from "node:fs/promises";
1470
- import * as path5 from "node:path";
1470
+ import * as path4 from "node:path";
1471
1471
  var tsModule3 = null;
1472
1472
  async function loadTs3() {
1473
1473
  if (!tsModule3) {
@@ -1804,7 +1804,7 @@ async function extractDirectorySkeleton(opts) {
1804
1804
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build") {
1805
1805
  continue;
1806
1806
  }
1807
- const fullPath = path5.join(dir, entry.name);
1807
+ const fullPath = path4.join(dir, entry.name);
1808
1808
  if (entry.isDirectory()) {
1809
1809
  await scan(fullPath);
1810
1810
  } else if (entry.isFile() && isIndexablePath(fullPath)) {
@@ -1832,7 +1832,7 @@ async function extractDirectorySkeleton(opts) {
1832
1832
  totalSkelChars += res.skeleton.length;
1833
1833
  totalOrigLines += res.stats.originalLines;
1834
1834
  totalSkelLines += res.stats.skeletonLines;
1835
- const rel = path5.relative(opts.dirPath, fp).replace(/\\/g, "/");
1835
+ const rel = path4.relative(opts.dirPath, fp).replace(/\\/g, "/");
1836
1836
  combinedParts.push(
1837
1837
  `// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ${rel} (${res.lang}) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1838
1838
  ${res.skeleton}`
@@ -1869,7 +1869,7 @@ async function generateRepoMap(opts) {
1869
1869
  const projectRoot = opts.projectRoot;
1870
1870
  const maxTokens = opts.maxTokens ?? 1200;
1871
1871
  const charBudget = maxTokens * 4;
1872
- const focusSet = new Set((opts.focusFiles ?? []).map((f) => path6.resolve(projectRoot, f)));
1872
+ const focusSet = new Set((opts.focusFiles ?? []).map((f) => path5.resolve(projectRoot, f)));
1873
1873
  const allFiles = [];
1874
1874
  async function scan(dir) {
1875
1875
  if (allFiles.length > 500) return;
@@ -1883,7 +1883,7 @@ async function generateRepoMap(opts) {
1883
1883
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
1884
1884
  continue;
1885
1885
  }
1886
- const fullPath = path6.join(dir, entry.name);
1886
+ const fullPath = path5.join(dir, entry.name);
1887
1887
  if (entry.isDirectory()) {
1888
1888
  await scan(fullPath);
1889
1889
  } else if (entry.isFile() && isIndexablePath(fullPath)) {
@@ -1903,7 +1903,7 @@ async function generateRepoMap(opts) {
1903
1903
  }
1904
1904
  const scoredFiles = [];
1905
1905
  for (const file of allFiles) {
1906
- const relPath = path6.relative(projectRoot, file).replace(/\\/g, "/");
1906
+ const relPath = path5.relative(projectRoot, file).replace(/\\/g, "/");
1907
1907
  let score = 10;
1908
1908
  if (focusSet.has(file)) {
1909
1909
  score += 100;
@@ -2009,7 +2009,6 @@ var codebaseRepoMapTool = {
2009
2009
 
2010
2010
  // src/codebase-index/codebase-skeleton-tool.ts
2011
2011
  import * as fs5 from "node:fs/promises";
2012
- import * as path7 from "node:path";
2013
2012
  import { toErrorMessage as toErrorMessage8 } from "@wrongstack/core/utils";
2014
2013
  var codebaseSkeletonTool = {
2015
2014
  name: "codebase-skeleton",
@@ -2049,7 +2048,7 @@ var codebaseSkeletonTool = {
2049
2048
  additionalProperties: false
2050
2049
  },
2051
2050
  async execute(input, ctx) {
2052
- const targetPath = path7.isAbsolute(input.path) ? input.path : path7.resolve(ctx.projectRoot ?? process.cwd(), input.path);
2051
+ const targetPath = await safeResolveProjectPath(input.path, ctx);
2053
2052
  let stat3;
2054
2053
  try {
2055
2054
  stat3 = await fs5.stat(targetPath);
@@ -2191,25 +2190,25 @@ var codebaseStatsTool = {
2191
2190
 
2192
2191
  // src/codebase-index/codebase-targeted-test-tool.ts
2193
2192
  import * as fs6 from "node:fs/promises";
2194
- import * as path8 from "node:path";
2193
+ import * as path6 from "node:path";
2195
2194
  import { toErrorMessage as toErrorMessage9 } from "@wrongstack/core/utils";
2196
2195
  var TEST_FILE_REGEX2 = /(?:test|spec|mock|fixture|bench)[s]?[/\\._]/i;
2197
2196
  async function findConventionTestFiles(projectRoot, sourceRelPath) {
2198
- const parsed = path8.parse(sourceRelPath);
2197
+ const parsed = path6.parse(sourceRelPath);
2199
2198
  const candidates = [
2200
- path8.join(parsed.dir, `${parsed.name}.test${parsed.ext}`),
2201
- path8.join(parsed.dir, `${parsed.name}.spec${parsed.ext}`),
2202
- path8.join(parsed.dir, `${parsed.name}_test${parsed.ext}`),
2203
- path8.join(parsed.dir, `test_${parsed.name}${parsed.ext}`),
2204
- path8.join("tests", `${parsed.name}.test${parsed.ext}`),
2205
- path8.join("tests", `${parsed.name}.spec${parsed.ext}`),
2206
- path8.join("test", `${parsed.name}.test${parsed.ext}`),
2207
- path8.join(parsed.dir, "__tests__", `${parsed.name}.test${parsed.ext}`),
2208
- path8.join(parsed.dir, "__tests__", `${parsed.name}${parsed.ext}`)
2199
+ path6.join(parsed.dir, `${parsed.name}.test${parsed.ext}`),
2200
+ path6.join(parsed.dir, `${parsed.name}.spec${parsed.ext}`),
2201
+ path6.join(parsed.dir, `${parsed.name}_test${parsed.ext}`),
2202
+ path6.join(parsed.dir, `test_${parsed.name}${parsed.ext}`),
2203
+ path6.join("tests", `${parsed.name}.test${parsed.ext}`),
2204
+ path6.join("tests", `${parsed.name}.spec${parsed.ext}`),
2205
+ path6.join("test", `${parsed.name}.test${parsed.ext}`),
2206
+ path6.join(parsed.dir, "__tests__", `${parsed.name}.test${parsed.ext}`),
2207
+ path6.join(parsed.dir, "__tests__", `${parsed.name}${parsed.ext}`)
2209
2208
  ];
2210
2209
  const found = [];
2211
2210
  for (const cand of candidates) {
2212
- const absPath = path8.resolve(projectRoot, cand);
2211
+ const absPath = path6.resolve(projectRoot, cand);
2213
2212
  try {
2214
2213
  const st = await fs6.stat(absPath);
2215
2214
  if (st.isFile()) {
@@ -2268,7 +2267,7 @@ var codebaseTargetedTestTool = {
2268
2267
  transitive: true
2269
2268
  });
2270
2269
  for (const site of serviced.calls) {
2271
- const relPath = path8.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
2270
+ const relPath = path6.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
2272
2271
  if (TEST_FILE_REGEX2.test(relPath)) {
2273
2272
  suitesSet.add(relPath);
2274
2273
  }
@@ -2353,7 +2352,7 @@ ${streamRes.stderr}`.trim(),
2353
2352
 
2354
2353
  // src/codebase-index/dead-code-scan.ts
2355
2354
  import * as fs7 from "node:fs";
2356
- import * as path9 from "node:path";
2355
+ import * as path7 from "node:path";
2357
2356
  var deadCodeScanTool = {
2358
2357
  name: "dead-code-scan",
2359
2358
  category: "Project",
@@ -2405,8 +2404,8 @@ function tryReadJson(filePath) {
2405
2404
  }
2406
2405
  }
2407
2406
  function resolveAgainst(base, relative7) {
2408
- if (path9.isAbsolute(relative7)) return relative7;
2409
- return path9.resolve(base, relative7);
2407
+ if (path7.isAbsolute(relative7)) return relative7;
2408
+ return path7.resolve(base, relative7);
2410
2409
  }
2411
2410
  function discoverEntryPoints(projectRoot, userEntryPoints) {
2412
2411
  const entries = /* @__PURE__ */ new Set();
@@ -2416,7 +2415,7 @@ function discoverEntryPoints(projectRoot, userEntryPoints) {
2416
2415
  if (fs7.existsSync(resolved)) entries.add(resolved);
2417
2416
  }
2418
2417
  }
2419
- const rootPkg = tryReadJson(path9.join(projectRoot, "package.json"));
2418
+ const rootPkg = tryReadJson(path7.join(projectRoot, "package.json"));
2420
2419
  if (rootPkg) {
2421
2420
  addPkgJsonEntryPoints(projectRoot, rootPkg, entries);
2422
2421
  }
@@ -2430,34 +2429,34 @@ function discoverEntryPoints(projectRoot, userEntryPoints) {
2430
2429
  workspaces = [];
2431
2430
  }
2432
2431
  for (const wsDir of workspaces) {
2433
- const pkgJsonPath = path9.join(wsDir, "package.json");
2432
+ const pkgJsonPath = path7.join(wsDir, "package.json");
2434
2433
  const pkg = tryReadJson(pkgJsonPath);
2435
2434
  if (pkg) {
2436
2435
  addPkgJsonEntryPoints(wsDir, pkg, entries);
2437
- const convention1 = path9.join(wsDir, "src", "index.ts");
2436
+ const convention1 = path7.join(wsDir, "src", "index.ts");
2438
2437
  if (fs7.existsSync(convention1)) entries.add(convention1);
2439
- const convention2 = path9.join(wsDir, "src", "main.ts");
2438
+ const convention2 = path7.join(wsDir, "src", "main.ts");
2440
2439
  if (fs7.existsSync(convention2)) entries.add(convention2);
2441
- const convention3 = path9.join(wsDir, "index.ts");
2440
+ const convention3 = path7.join(wsDir, "index.ts");
2442
2441
  if (fs7.existsSync(convention3)) entries.add(convention3);
2443
2442
  }
2444
2443
  }
2445
2444
  if (!rootPkg || !workspaces.length) {
2446
2445
  for (const name of ["src/index.ts", "src/main.ts", "index.ts"]) {
2447
- const convention = path9.join(projectRoot, name);
2446
+ const convention = path7.join(projectRoot, name);
2448
2447
  if (fs7.existsSync(convention)) entries.add(convention);
2449
2448
  }
2450
2449
  }
2451
2450
  return [...entries];
2452
2451
  }
2453
2452
  var BUILD_OUTPUT_DIRS = ["dist", "out", "build", "release"];
2454
- var BUILD_OUTPUT_DIR_NAMES = BUILD_OUTPUT_DIRS.map((d) => `${path9.sep}${d}${path9.sep}`);
2453
+ var BUILD_OUTPUT_DIR_NAMES = BUILD_OUTPUT_DIRS.map((d) => `${path7.sep}${d}${path7.sep}`);
2455
2454
  function trySourceEquivalent(resolved) {
2456
- resolved = resolved.replace(/[/\\]/g, path9.sep);
2455
+ resolved = resolved.replace(/[/\\]/g, path7.sep);
2457
2456
  for (const marker of BUILD_OUTPUT_DIR_NAMES) {
2458
2457
  const idx = resolved.indexOf(marker);
2459
2458
  if (idx === -1) continue;
2460
- const base = resolved.replace(marker, `${path9.sep}src${path9.sep}`);
2459
+ const base = resolved.replace(marker, `${path7.sep}src${path7.sep}`);
2461
2460
  const candidate = base.replace(/\.(js|mjs|cjs)$/, ".ts");
2462
2461
  if (candidate !== base && fs7.existsSync(candidate)) {
2463
2462
  return candidate;
@@ -2522,18 +2521,18 @@ function expandGlobPattern(entry, projectRoot) {
2522
2521
  const dirs = [];
2523
2522
  if (entry.includes("*")) {
2524
2523
  const base = entry.replace(/\/\*+$/, "");
2525
- const baseDir = path9.resolve(projectRoot, base);
2524
+ const baseDir = path7.resolve(projectRoot, base);
2526
2525
  try {
2527
2526
  const children = fs7.readdirSync(baseDir, { withFileTypes: true });
2528
2527
  for (const child of children) {
2529
2528
  if (child.isDirectory()) {
2530
- dirs.push(path9.join(baseDir, child.name));
2529
+ dirs.push(path7.join(baseDir, child.name));
2531
2530
  }
2532
2531
  }
2533
2532
  } catch {
2534
2533
  }
2535
2534
  } else {
2536
- dirs.push(path9.resolve(projectRoot, entry));
2535
+ dirs.push(path7.resolve(projectRoot, entry));
2537
2536
  }
2538
2537
  return dirs;
2539
2538
  }
@@ -2550,7 +2549,7 @@ function extractWorkspaceGlobs(pkg, projectRoot) {
2550
2549
  return dirs;
2551
2550
  }
2552
2551
  function extractPnpmWorkspaceDirs(projectRoot) {
2553
- const yamlPath = path9.join(projectRoot, "pnpm-workspace.yaml");
2552
+ const yamlPath = path7.join(projectRoot, "pnpm-workspace.yaml");
2554
2553
  if (!fs7.existsSync(yamlPath)) return [];
2555
2554
  try {
2556
2555
  const content = fs7.readFileSync(yamlPath, "utf8");
@@ -2587,8 +2586,8 @@ function extractPnpmWorkspaceDirs(projectRoot) {
2587
2586
  }
2588
2587
  function resolveModulePath(importerPath, moduleSpecifier, indexedFiles) {
2589
2588
  if (!moduleSpecifier.startsWith(".")) return [];
2590
- const dir = path9.dirname(importerPath);
2591
- const base = path9.resolve(dir, moduleSpecifier);
2589
+ const dir = path7.dirname(importerPath);
2590
+ const base = path7.resolve(dir, moduleSpecifier);
2592
2591
  const results = [];
2593
2592
  const stripped = base.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/, "");
2594
2593
  const skipBase = stripped !== base && /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(base);
@@ -2600,18 +2599,18 @@ function resolveModulePath(importerPath, moduleSpecifier, indexedFiles) {
2600
2599
  if (indexedFiles.has(candidate + ".jsx")) results.push(candidate + ".jsx");
2601
2600
  if (indexedFiles.has(candidate + ".mjs")) results.push(candidate + ".mjs");
2602
2601
  if (indexedFiles.has(candidate + ".cjs")) results.push(candidate + ".cjs");
2603
- if (indexedFiles.has(path9.join(candidate, "index.ts")))
2604
- results.push(path9.join(candidate, "index.ts"));
2605
- if (indexedFiles.has(path9.join(candidate, "index.tsx")))
2606
- results.push(path9.join(candidate, "index.tsx"));
2607
- if (indexedFiles.has(path9.join(candidate, "index.js")))
2608
- results.push(path9.join(candidate, "index.js"));
2609
- if (indexedFiles.has(path9.join(candidate, "index.jsx")))
2610
- results.push(path9.join(candidate, "index.jsx"));
2611
- if (indexedFiles.has(path9.join(candidate, "index.mjs")))
2612
- results.push(path9.join(candidate, "index.mjs"));
2613
- if (indexedFiles.has(path9.join(candidate, "index.cjs")))
2614
- results.push(path9.join(candidate, "index.cjs"));
2602
+ if (indexedFiles.has(path7.join(candidate, "index.ts")))
2603
+ results.push(path7.join(candidate, "index.ts"));
2604
+ if (indexedFiles.has(path7.join(candidate, "index.tsx")))
2605
+ results.push(path7.join(candidate, "index.tsx"));
2606
+ if (indexedFiles.has(path7.join(candidate, "index.js")))
2607
+ results.push(path7.join(candidate, "index.js"));
2608
+ if (indexedFiles.has(path7.join(candidate, "index.jsx")))
2609
+ results.push(path7.join(candidate, "index.jsx"));
2610
+ if (indexedFiles.has(path7.join(candidate, "index.mjs")))
2611
+ results.push(path7.join(candidate, "index.mjs"));
2612
+ if (indexedFiles.has(path7.join(candidate, "index.cjs")))
2613
+ results.push(path7.join(candidate, "index.cjs"));
2615
2614
  }
2616
2615
  return [...new Set(results)];
2617
2616
  }
@@ -2643,7 +2642,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
2643
2642
  symbolById.set(s.id, s);
2644
2643
  }
2645
2644
  const discoveredFiles = discoverEntryPoints(projectRoot, opts.userEntryPoints);
2646
- const entryFileSet = new Set(discoveredFiles.map((f) => path9.resolve(f)));
2645
+ const entryFileSet = new Set(discoveredFiles.map((f) => path7.resolve(f)));
2647
2646
  const indexedFiles = /* @__PURE__ */ new Set();
2648
2647
  for (const s of allSymbols) indexedFiles.add(s.file);
2649
2648
  for (const fm of store.getAllFileMetas()) indexedFiles.add(fm.file);
@@ -2759,7 +2758,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
2759
2758
  const deadPackages = [];
2760
2759
  const pkgEntries = findPackageEntries(projectRoot);
2761
2760
  for (const [pkgName, pkgDir] of pkgEntries) {
2762
- const pkgFiles = allSymbols.filter((s) => s.file.startsWith(pkgDir + path9.sep));
2761
+ const pkgFiles = allSymbols.filter((s) => s.file.startsWith(pkgDir + path7.sep));
2763
2762
  if (pkgFiles.length === 0) continue;
2764
2763
  const pkgUsed = pkgFiles.filter((s) => alive.has(s.id));
2765
2764
  if (pkgUsed.length === 0) {
@@ -2795,7 +2794,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
2795
2794
  }
2796
2795
  function findPackageEntries(projectRoot) {
2797
2796
  const pkgMap = /* @__PURE__ */ new Map();
2798
- const rootPkg = tryReadJson(path9.join(projectRoot, "package.json"));
2797
+ const rootPkg = tryReadJson(path7.join(projectRoot, "package.json"));
2799
2798
  if (rootPkg && typeof rootPkg.name === "string") {
2800
2799
  pkgMap.set(rootPkg.name, projectRoot);
2801
2800
  }
@@ -2805,7 +2804,7 @@ function findPackageEntries(projectRoot) {
2805
2804
  wsDirs = extractPnpmWorkspaceDirs(projectRoot);
2806
2805
  }
2807
2806
  for (const wsDir of wsDirs) {
2808
- const wsPkg = tryReadJson(path9.join(wsDir, "package.json"));
2807
+ const wsPkg = tryReadJson(path7.join(wsDir, "package.json"));
2809
2808
  if (wsPkg && typeof wsPkg.name === "string") {
2810
2809
  pkgMap.set(wsPkg.name, wsDir);
2811
2810
  }
@@ -2835,4 +2834,4 @@ export {
2835
2834
  deadCodeScanTool,
2836
2835
  runDeadCodeScan
2837
2836
  };
2838
- //# sourceMappingURL=chunk-YF3D5INN.js.map
2837
+ //# sourceMappingURL=chunk-RK47IWO3.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  builtinTools
3
- } from "./chunk-K23JNFE3.js";
3
+ } from "./chunk-VALQFAY2.js";
4
4
 
5
5
  // src/pack.ts
6
6
  var builtinToolsPack = {
@@ -12,4 +12,4 @@ var builtinToolsPack = {
12
12
  export {
13
13
  builtinToolsPack
14
14
  };
15
- //# sourceMappingURL=chunk-MX25MTDJ.js.map
15
+ //# sourceMappingURL=chunk-SYXW3Y5Z.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseFilesContent
3
- } from "./chunk-JJQB6R7Y.js";
3
+ } from "./chunk-TX3R5NVV.js";
4
4
  import {
5
5
  INDEXABLE_EXTENSIONS,
6
6
  LANG_FAMILY_ENTRIES,
@@ -1923,6 +1923,7 @@ var SYMBOL_VECTORS_TABLE_SQL = `
1923
1923
  // src/codebase-index/writer-refs.ts
1924
1924
  var FAMILY_MATCH_SQL = `(
1925
1925
  sym.lang = refs.lang
1926
+ OR refs.lang = ''
1926
1927
  OR EXISTS (
1927
1928
  SELECT 1 FROM lang_family lf1
1928
1929
  JOIN lang_family lf2 ON lf1.family = lf2.family
@@ -3824,7 +3825,7 @@ var ParserWorkerPool = class {
3824
3825
  */
3825
3826
  async reparseInline(batch, orphaned, workerId) {
3826
3827
  try {
3827
- const { parseFileContent } = await import("./parser-dispatch-X62UWXJS.js");
3828
+ const { parseFileContent } = await import("./parser-dispatch-3PDBKIQ7.js");
3828
3829
  for (const item of orphaned) {
3829
3830
  if (batch.settled) return;
3830
3831
  try {
@@ -4613,4 +4614,4 @@ export {
4613
4614
  incomingCallsService,
4614
4615
  outgoingCallsService
4615
4616
  };
4616
- //# sourceMappingURL=chunk-BLCSYKNN.js.map
4617
+ //# sourceMappingURL=chunk-TFMVHYJI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolvePythonBinary
3
- } from "./chunk-ZLTFLC25.js";
3
+ } from "./chunk-IIF5HIVF.js";
4
4
  import {
5
5
  parseParserBatchOutput,
6
6
  withSpawnGate
@@ -832,7 +832,7 @@ async function dispatch(file, content, lang) {
832
832
  return parseSymbols({ file, content, lang: "go" });
833
833
  }
834
834
  case "py": {
835
- const { parseSymbols } = await import("./py-parser-TDXSQZBC.js");
835
+ const { parseSymbols } = await import("./py-parser-RFWG2HYI.js");
836
836
  return parseSymbols({ file, content, lang: "py" });
837
837
  }
838
838
  case "rs": {
@@ -863,16 +863,16 @@ async function dispatch(file, content, lang) {
863
863
  case "shell":
864
864
  case "elixir": {
865
865
  try {
866
- const { parseSymbols: parseSymbols2 } = await import("./tree-sitter-parser-AIERW3YI.js");
866
+ const { parseSymbols: parseSymbols2 } = await import("./tree-sitter-parser-FGKHJGSX.js");
867
867
  const parsed = await parseSymbols2({ file, content, lang });
868
868
  if (parsed.symbols.length > 0) return parsed;
869
869
  } catch {
870
870
  }
871
- const { parseSymbols } = await import("./generic-parser-VUXDIAOZ.js");
871
+ const { parseSymbols } = await import("./generic-parser-WFMIRHBX.js");
872
872
  return parseSymbols({ file, content, lang });
873
873
  }
874
874
  default: {
875
- const { parseSymbols } = await import("./generic-parser-VUXDIAOZ.js");
875
+ const { parseSymbols } = await import("./generic-parser-WFMIRHBX.js");
876
876
  return parseSymbols({ file, content, lang });
877
877
  }
878
878
  }
@@ -889,4 +889,4 @@ export {
889
889
  parseFileContent,
890
890
  parseFilesContent
891
891
  };
892
- //# sourceMappingURL=chunk-JJQB6R7Y.js.map
892
+ //# sourceMappingURL=chunk-TX3R5NVV.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  normalizeCommandOutput,
6
6
  safeResolveReal
7
- } from "./chunk-D33S4RQG.js";
7
+ } from "./chunk-QLF74MSV.js";
8
8
 
9
9
  // src/languages/detect.ts
10
10
  import { createHash } from "node:crypto";
@@ -3515,4 +3515,4 @@ export {
3515
3515
  languagePackageTool,
3516
3516
  languageInfoTool
3517
3517
  };
3518
- //# sourceMappingURL=chunk-SOG7XIRF.js.map
3518
+ //# sourceMappingURL=chunk-UC3RKRIV.js.map