pi-lens 4.4.0 → 4.4.2

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 (150) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/README.md +1 -0
  3. package/config/dependency-cruiser-eager-allowlist.json +3 -1
  4. package/dist/{chunk-IXEBJSUE.js → chunk-23WOO7TX.js} +11 -10
  5. package/dist/{chunk-E2WFBRHM.js → chunk-2B73ZPOK.js} +3 -3
  6. package/dist/{chunk-DQ2NZ7C4.js → chunk-2BBLFX75.js} +139 -11
  7. package/dist/{chunk-ZMOL6RQC.js → chunk-2CD5RS6M.js} +2 -2
  8. package/dist/{chunk-VD4JQCQC.js → chunk-2ZGIZPDG.js} +38 -37
  9. package/dist/{chunk-DIULIWKU.js → chunk-34WSVGEM.js} +29 -3
  10. package/dist/chunk-3JNKMP3B.js +17 -0
  11. package/dist/{chunk-HVUZXSWK.js → chunk-3UUPUE3O.js} +45 -41
  12. package/dist/{chunk-5RXBNSW2.js → chunk-3VPVG5SU.js} +16 -8
  13. package/dist/chunk-3WA4HP4I.js +55 -0
  14. package/dist/chunk-466Z26MG.js +30 -0
  15. package/dist/{chunk-34U7PLGE.js → chunk-4UNXBNE2.js} +12 -11
  16. package/dist/{chunk-E4MAEDPM.js → chunk-4W4VLAPJ.js} +12 -11
  17. package/dist/{chunk-GUOGVTCQ.js → chunk-52FUZI6K.js} +4 -2
  18. package/dist/chunk-5JM2524W.js +84 -0
  19. package/dist/{chunk-VHQLPIRJ.js → chunk-5NGR67U5.js} +2 -2
  20. package/dist/{chunk-DFVMIKMQ.js → chunk-66SXUJCA.js} +45 -9
  21. package/dist/{chunk-OQGFCZJ4.js → chunk-66VMUL7Q.js} +16 -16
  22. package/dist/{chunk-HWBZIGMJ.js → chunk-67WMNWEE.js} +9 -8
  23. package/dist/{chunk-6QIUX4EP.js → chunk-6C7JWPCP.js} +7 -7
  24. package/dist/{chunk-47D2BO4S.js → chunk-6GFRNVYR.js} +11 -10
  25. package/dist/{chunk-ZAWW3AF6.js → chunk-6SDEP3AJ.js} +9 -8
  26. package/dist/{chunk-TGPXLY2J.js → chunk-724UL2TJ.js} +38 -2
  27. package/dist/{chunk-YLF3PPT5.js → chunk-76MWC2K6.js} +3 -3
  28. package/dist/{chunk-F3P7VQ7H.js → chunk-7DYBLXYA.js} +3 -3
  29. package/dist/{chunk-AJ3QXTRQ.js → chunk-7ULNCDCO.js} +37 -35
  30. package/dist/{chunk-UK3CMEAL.js → chunk-AOHZU2BM.js} +1 -1
  31. package/dist/{chunk-F3AU2TMM.js → chunk-ARJ6PLFH.js} +44 -28
  32. package/dist/{chunk-U3VGR4VU.js → chunk-AW7R2GWG.js} +65 -8
  33. package/dist/{chunk-FJNKANOS.js → chunk-BKE7E7TC.js} +10 -9
  34. package/dist/{chunk-4W2PLC4J.js → chunk-BRGDSBJE.js} +13 -12
  35. package/dist/{chunk-VN2AXLEX.js → chunk-C34ZXZ7O.js} +102 -16
  36. package/dist/{chunk-T4ERT73Y.js → chunk-CF24OIYI.js} +21 -20
  37. package/dist/{chunk-NMABWBZN.js → chunk-CHOW74WE.js} +1 -1
  38. package/dist/{chunk-ARFCXG7S.js → chunk-CO2G5PHH.js} +2 -2
  39. package/dist/{chunk-AS44CFQ4.js → chunk-EETY4LF7.js} +24 -10
  40. package/dist/{chunk-I3R7GKDR.js → chunk-EJIUXPBX.js} +1 -1
  41. package/dist/{chunk-B3I2UUT4.js → chunk-ESBQHFMJ.js} +653 -251
  42. package/dist/{chunk-O5WILGMI.js → chunk-FLKWCIZH.js} +8 -5
  43. package/dist/{chunk-LNAKEO63.js → chunk-GAEGEPOC.js} +4 -4
  44. package/dist/{chunk-V7R425XG.js → chunk-GBPP5P7X.js} +4 -4
  45. package/dist/{chunk-XK4CIILI.js → chunk-GHB6AYCP.js} +27 -26
  46. package/dist/{chunk-7FBF7NPR.js → chunk-GOYRYZ2R.js} +29 -26
  47. package/dist/{chunk-JOLITGCC.js → chunk-GXW6K4YJ.js} +1 -1
  48. package/dist/{chunk-NXPS2L6U.js → chunk-GZYBXISR.js} +9 -9
  49. package/dist/{chunk-OAXNDZJ7.js → chunk-IBGIOBEE.js} +8 -4
  50. package/dist/{chunk-IIXOAGHR.js → chunk-IBRALRBR.js} +19 -15
  51. package/dist/{chunk-7F72PXY2.js → chunk-IXXDFY73.js} +3 -3
  52. package/dist/chunk-IZSHAIJ7.js +26 -0
  53. package/dist/{chunk-N3YQJI6O.js → chunk-JAU72XNY.js} +20 -15
  54. package/dist/chunk-JMYYOTQG.js +77 -0
  55. package/dist/{chunk-NL5GLMFI.js → chunk-JSQFTSC6.js} +12 -11
  56. package/dist/{chunk-IVP5KAB7.js → chunk-JWA5I3SR.js} +35 -21
  57. package/dist/{chunk-Y4T27COV.js → chunk-KBG47GHP.js} +4 -4
  58. package/dist/{chunk-PWFHBTSF.js → chunk-L3BLXZG7.js} +2 -2
  59. package/dist/chunk-LOP6GRPH.js +31 -0
  60. package/dist/chunk-MQLUAEOC.js +162 -0
  61. package/dist/{chunk-RPD5K5NC.js → chunk-MRXKYPCS.js} +2 -2
  62. package/dist/{chunk-Q5U6FMDI.js → chunk-N2H3ZPZY.js} +59 -7
  63. package/dist/{chunk-27BBHSZC.js → chunk-N3X6Q4YT.js} +3 -3
  64. package/dist/{chunk-UY752QSN.js → chunk-NW7BOILN.js} +19 -17
  65. package/dist/{chunk-TLGFBM3F.js → chunk-ODBNXWT4.js} +302 -113
  66. package/dist/{chunk-TT22N74J.js → chunk-OG5UUPN7.js} +13 -13
  67. package/dist/{chunk-C2AUYXQH.js → chunk-OXXKQCSV.js} +6 -6
  68. package/dist/{chunk-PAK6IDME.js → chunk-P7266HLM.js} +2 -2
  69. package/dist/{chunk-52H5B5TC.js → chunk-PFNSLWU5.js} +31 -30
  70. package/dist/{chunk-5ZEJHV35.js → chunk-PHDMFAKM.js} +12 -2
  71. package/dist/{chunk-3I5QFT3N.js → chunk-PNQDPDRC.js} +6 -3
  72. package/dist/{chunk-TVN5N6GY.js → chunk-PV6LR5P5.js} +6057 -1311
  73. package/dist/{chunk-AHDW3GPE.js → chunk-Q6ZWTCLY.js} +24 -22
  74. package/dist/{chunk-RUOG5D2C.js → chunk-Q7DUK4LX.js} +5 -5
  75. package/dist/{chunk-YSNFMJKN.js → chunk-QGQ5CCCG.js} +2 -2
  76. package/dist/{chunk-LW6XKDZQ.js → chunk-QHJ6DQ2R.js} +287 -38
  77. package/dist/{chunk-GVXA6CCE.js → chunk-QILIYSJF.js} +1 -1
  78. package/dist/{chunk-22AVIGXS.js → chunk-QOBUHWHX.js} +12 -7
  79. package/dist/{chunk-5THXD6X5.js → chunk-QQNQ7SJW.js} +2 -75
  80. package/dist/{chunk-4RERDEXR.js → chunk-QZVW3AAK.js} +50 -41
  81. package/dist/{chunk-AWE5TMPO.js → chunk-R3PCY3YS.js} +14 -13
  82. package/dist/{chunk-HHYAELLJ.js → chunk-RPLINGVB.js} +7 -7
  83. package/dist/{chunk-EOKRQ3SA.js → chunk-RWWYJ623.js} +10 -1
  84. package/dist/{chunk-YGVYKNSN.js → chunk-SAEFPSB6.js} +59 -12
  85. package/dist/{chunk-K6VYLB2U.js → chunk-TYM6OUIT.js} +13 -12
  86. package/dist/{chunk-AJXODZY6.js → chunk-UXGETRP4.js} +13 -12
  87. package/dist/{chunk-I7SPGOWI.js → chunk-UZ3TUTRV.js} +1 -1
  88. package/dist/{chunk-TO6WL3GM.js → chunk-VCHXCQFG.js} +12 -2
  89. package/dist/{chunk-BRJKOBZP.js → chunk-VITUCP5A.js} +17 -6
  90. package/dist/{chunk-WONERJTP.js → chunk-VRZP76YM.js} +1 -1
  91. package/dist/{chunk-OS32RNR2.js → chunk-VSSBEUFT.js} +16 -15
  92. package/dist/{chunk-VDBPVIKD.js → chunk-VWCXW2E7.js} +1 -1
  93. package/dist/{chunk-NKOUFPQF.js → chunk-WOA4LN2R.js} +2 -2
  94. package/dist/{chunk-RIISMHKN.js → chunk-WOKKRCJ5.js} +15 -13
  95. package/dist/{chunk-XECLWQZN.js → chunk-WU567RSC.js} +13 -10
  96. package/dist/{chunk-V5PXFSZK.js → chunk-XCJN5IJU.js} +4 -4
  97. package/dist/{chunk-ORTMY4Q4.js → chunk-XKIZ2HNN.js} +22 -14
  98. package/dist/{chunk-6VCD4VKZ.js → chunk-XMSXXAHW.js} +2 -2
  99. package/dist/chunk-XPZPXCBV.js +28 -0
  100. package/dist/{chunk-O6TQT6RI.js → chunk-XTMJ7XDT.js} +1 -1
  101. package/dist/{chunk-VNMT7C64.js → chunk-XVF2VVXP.js} +5 -3
  102. package/dist/chunk-Z527N6YQ.js +28 -0
  103. package/dist/{chunk-NTUJEGDZ.js → chunk-ZANLILYD.js} +22 -2
  104. package/dist/{chunk-6P62QVEA.js → chunk-ZGDGW2V3.js} +2 -2
  105. package/dist/{chunk-ODEEOXPH.js → chunk-ZHFZWTZV.js} +12 -11
  106. package/dist/{chunk-AJVLWNFN.js → chunk-ZXYDQ3TZ.js} +5 -5
  107. package/dist/index.js +102097 -97778
  108. package/dist/mcp/analyze-cli.js +18 -8
  109. package/dist/mcp/cli.js +48 -37
  110. package/dist/mcp/server.js +695 -426
  111. package/dist/mcp/worker.js +66 -55
  112. package/dist/probes/installer.js +20 -19
  113. package/docs/ast-grep_rules_catalog.md +2 -2
  114. package/docs/astplayground.md +1 -1
  115. package/docs/configuration.md +38 -2
  116. package/docs/custom-rules.md +25 -2
  117. package/docs/dependencies.md +3 -0
  118. package/docs/environment-variables.md +34 -6
  119. package/docs/features.md +39 -3
  120. package/docs/globalconfig.md +3 -1
  121. package/docs/language-coverage.md +2 -1
  122. package/docs/lsp-capability-matrix.md +29 -6
  123. package/docs/lsp-idle-eviction.md +38 -47
  124. package/docs/pi-lens-fixer.md +13 -5
  125. package/docs/pi-lens-merge-policy.md +48 -1
  126. package/docs/pi-lens-monitor.md +3 -1
  127. package/docs/pi-lens-retro.md +2 -1
  128. package/docs/pi-lens-reviewer.md +19 -3
  129. package/docs/pi-lens-subagent.md +2 -0
  130. package/docs/real-harness.md +17 -0
  131. package/docs/schema/pi-lens-config-v1.json +565 -0
  132. package/docs/servercapabilities.md +18 -4
  133. package/docs/settings.md +2 -1
  134. package/docs/word-index.md +6 -0
  135. package/package.json +1 -1
  136. package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
  137. package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
  138. package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
  139. package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
  140. package/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
  141. package/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
  142. package/dist/chunk-54B42YRX.js +0 -27
  143. package/dist/chunk-CGGAIP7J.js +0 -29
  144. package/dist/chunk-D6QS3U6M.js +0 -30
  145. package/dist/chunk-HMFXILPV.js +0 -83
  146. package/dist/chunk-LSMJ6KBE.js +0 -4139
  147. package/dist/chunk-NTHH2J74.js +0 -27
  148. package/dist/chunk-RPD4ZSB7.js +0 -25
  149. package/dist/chunk-T6D4Q4AQ.js +0 -54
  150. package/dist/chunk-VCSRSYLF.js +0 -81
@@ -2,27 +2,38 @@ import { createRequire as __pilensCreateRequire } from "node:module"; const requ
2
2
  import {
3
3
  createAvailabilityProbeFlight,
4
4
  probeToolAsync
5
- } from "./chunk-EOKRQ3SA.js";
5
+ } from "./chunk-RWWYJ623.js";
6
6
  import {
7
7
  classifyProbeFailure,
8
8
  createAvailabilityLatch,
9
9
  isTransientDecision,
10
10
  logAvailabilityDecision,
11
11
  startHostStallSampler
12
- } from "./chunk-WONERJTP.js";
12
+ } from "./chunk-VRZP76YM.js";
13
13
  import {
14
14
  createGenerationSource,
15
15
  safeSpawnAsync
16
- } from "./chunk-VN2AXLEX.js";
16
+ } from "./chunk-C34ZXZ7O.js";
17
+ import {
18
+ getProjectTrustState
19
+ } from "./chunk-ZANLILYD.js";
20
+ import {
21
+ recordDegradationOnce
22
+ } from "./chunk-JAU72XNY.js";
23
+ import {
24
+ logExtension
25
+ } from "./chunk-XTMJ7XDT.js";
17
26
  import {
18
27
  isAtOrAboveHomeDir,
28
+ isUnderDir,
19
29
  walkUpDirs
20
- } from "./chunk-Q5U6FMDI.js";
30
+ } from "./chunk-N2H3ZPZY.js";
21
31
 
22
32
  // dist/clients/package-manager.js
23
33
  import * as fs from "node:fs";
24
34
  import * as os from "node:os";
25
35
  import * as path from "node:path";
36
+ import { resolve as resolvePath } from "node:path";
26
37
  var PREFERENCE = [
27
38
  "npm",
28
39
  "pnpm",
@@ -254,6 +265,41 @@ var VENV_BIN_DIRS = [
254
265
  path.join(".venv", "Scripts"),
255
266
  path.join("venv", "Scripts")
256
267
  ];
268
+ var PROJECT_LOCAL_BIN_DIRS = [
269
+ ...NODE_MODULES_BIN_DIRS,
270
+ ...VENDOR_BIN_DIRS,
271
+ ...VENV_BIN_DIRS
272
+ ];
273
+ function localBinPath(value) {
274
+ return typeof value === "string" ? value : void 0;
275
+ }
276
+ function refuseLocalBin(tool, root) {
277
+ const trust = getProjectTrustState();
278
+ const resolvedRoot = resolvePath(root);
279
+ const subject = `project-local-binary:${resolvedRoot}:${tool}`;
280
+ if (recordDegradationOnce({
281
+ kind: "trust-refusal",
282
+ subject,
283
+ reason: `project-local binary refused: pi project trust is ${trust}`
284
+ })) {
285
+ logExtension({
286
+ subsystem: "project-trust",
287
+ level: "warn",
288
+ message: "project-local binary refused: mark the project trusted in pi or upgrade pi",
289
+ metadata: { tool, root: resolvedRoot, trust }
290
+ });
291
+ }
292
+ return { kind: "refused-by-trust", tool, root: resolvedRoot, trust };
293
+ }
294
+ function isProjectLocalBinPath(resolvedCommand, cwd) {
295
+ for (const ancestor of walkUpDirs(cwd)) {
296
+ if (isAtOrAboveHomeDir(ancestor, os.homedir()))
297
+ break;
298
+ if (PROJECT_LOCAL_BIN_DIRS.some((binDir) => isUnderDir(resolvedCommand, path.join(ancestor, binDir))))
299
+ return true;
300
+ }
301
+ return false;
302
+ }
257
303
  function expandCandidateNames(tools, windowsExt, isWindows) {
258
304
  return isWindows && windowsExt !== "" ? tools.flatMap((tool) => [`${tool}${windowsExt}`, tool]) : [...tools];
259
305
  }
@@ -276,18 +322,27 @@ function* localBinMatches(tools, startDir, options) {
276
322
  }
277
323
  }
278
324
  function findLocalBinUpwards(tool, startDir, options = {}) {
279
- return localBinMatches([tool], startDir, options).next().value;
325
+ const match = localBinMatches([tool], startDir, options).next().value;
326
+ if (match === void 0 || options.ceiling === false)
327
+ return match;
328
+ if (getProjectTrustState() !== "trusted")
329
+ return refuseLocalBin(tool, startDir);
330
+ return match;
280
331
  }
281
332
  function findLocalBinsAt(tools, dir, options = {}) {
282
333
  const { windowsExt = ".cmd", binDirs = NODE_MODULES_BIN_DIRS, isWindows = onWindows() } = options;
283
334
  const names = expandCandidateNames(tools, windowsExt, isWindows);
284
- return [...matchesInDir(path.resolve(dir), names, binDirs)];
335
+ const matches = [...matchesInDir(path.resolve(dir), names, binDirs)];
336
+ if (matches.length === 0 || getProjectTrustState() === "trusted")
337
+ return matches;
338
+ return [refuseLocalBin(tools.join(","), dir)];
285
339
  }
286
340
  function findLocalBinAt(tool, dir, options = {}) {
287
- return findLocalBinsAt([tool], dir, options)[0];
341
+ const match = findLocalBinsAt([tool], dir, options)[0];
342
+ return match;
288
343
  }
289
344
  async function findNodeToolBinary(tool, cwd, windowsExt = ".cmd") {
290
- return findLocalBinUpwards(tool, cwd, { windowsExt }) ?? await findGlobalBinary(tool, windowsExt);
345
+ return localBinPath(findLocalBinUpwards(tool, cwd, { windowsExt })) ?? await findGlobalBinary(tool, windowsExt);
291
346
  }
292
347
 
293
348
  export {
@@ -301,6 +356,8 @@ export {
301
356
  findGlobalBinary,
302
357
  VENDOR_BIN_DIRS,
303
358
  VENV_BIN_DIRS,
359
+ localBinPath,
360
+ isProjectLocalBinPath,
304
361
  findLocalBinUpwards,
305
362
  findLocalBinsAt,
306
363
  findLocalBinAt,
@@ -7,19 +7,20 @@ import {
7
7
  loadCallGraph,
8
8
  parseSymbolKey,
9
9
  saveCallGraph
10
- } from "./chunk-NKOUFPQF.js";
10
+ } from "./chunk-WOA4LN2R.js";
11
11
  import "./chunk-3MED75HT.js";
12
- import "./chunk-VN2AXLEX.js";
13
- import "./chunk-DQ2NZ7C4.js";
14
- import "./chunk-VNMT7C64.js";
12
+ import "./chunk-C34ZXZ7O.js";
13
+ import "./chunk-2BBLFX75.js";
14
+ import "./chunk-XVF2VVXP.js";
15
15
  import "./chunk-2EECBNC5.js";
16
- import "./chunk-N3YQJI6O.js";
17
- import "./chunk-O6TQT6RI.js";
18
- import "./chunk-5THXD6X5.js";
19
- import "./chunk-UK3CMEAL.js";
16
+ import "./chunk-JAU72XNY.js";
17
+ import "./chunk-XTMJ7XDT.js";
18
+ import "./chunk-JMYYOTQG.js";
19
+ import "./chunk-QQNQ7SJW.js";
20
+ import "./chunk-AOHZU2BM.js";
20
21
  import "./chunk-LJDODBBZ.js";
21
22
  import "./chunk-ABBOA7UD.js";
22
- import "./chunk-Q5U6FMDI.js";
23
+ import "./chunk-N2H3ZPZY.js";
23
24
  import "./chunk-NXL4FFQQ.js";
24
25
  export {
25
26
  CALL_GRAPH_CACHE_VERSION,
@@ -3,22 +3,23 @@ import {
3
3
  RustClient,
4
4
  resetRustAvailability,
5
5
  rustClient
6
- } from "./chunk-RPD5K5NC.js";
7
- import "./chunk-F3P7VQ7H.js";
8
- import "./chunk-EOKRQ3SA.js";
9
- import "./chunk-WONERJTP.js";
10
- import "./chunk-VN2AXLEX.js";
6
+ } from "./chunk-MRXKYPCS.js";
7
+ import "./chunk-7DYBLXYA.js";
8
+ import "./chunk-RWWYJ623.js";
9
+ import "./chunk-VRZP76YM.js";
10
+ import "./chunk-C34ZXZ7O.js";
11
11
  import "./chunk-BW5KFIQC.js";
12
- import "./chunk-DQ2NZ7C4.js";
13
- import "./chunk-VNMT7C64.js";
12
+ import "./chunk-2BBLFX75.js";
13
+ import "./chunk-XVF2VVXP.js";
14
14
  import "./chunk-2EECBNC5.js";
15
- import "./chunk-N3YQJI6O.js";
16
- import "./chunk-O6TQT6RI.js";
17
- import "./chunk-5THXD6X5.js";
18
- import "./chunk-UK3CMEAL.js";
15
+ import "./chunk-JAU72XNY.js";
16
+ import "./chunk-XTMJ7XDT.js";
17
+ import "./chunk-JMYYOTQG.js";
18
+ import "./chunk-QQNQ7SJW.js";
19
+ import "./chunk-AOHZU2BM.js";
19
20
  import "./chunk-LJDODBBZ.js";
20
21
  import "./chunk-ABBOA7UD.js";
21
- import "./chunk-Q5U6FMDI.js";
22
+ import "./chunk-N2H3ZPZY.js";
22
23
  import "./chunk-NXL4FFQQ.js";
23
24
  export {
24
25
  RustClient,
@@ -12,7 +12,7 @@ import {
12
12
  reportPiLensConfigRecords,
13
13
  resolveOnePiLensConfigDocument,
14
14
  warnIgnoredConfigOnce
15
- } from "./chunk-DQ2NZ7C4.js";
15
+ } from "./chunk-2BBLFX75.js";
16
16
  import {
17
17
  CANONICAL_GLOBAL_CONFIG_FILE,
18
18
  FRESHNESS_CADENCE_MS,
@@ -22,7 +22,7 @@ import {
22
22
  errorClassName,
23
23
  getPiLensGlobalConfigPath,
24
24
  getProductionGlobalConfigResolution
25
- } from "./chunk-VNMT7C64.js";
25
+ } from "./chunk-XVF2VVXP.js";
26
26
  import {
27
27
  DEFAULT_MAX_OUTPUT_BYTES,
28
28
  createBoundedOutputSink,
@@ -42,16 +42,16 @@ import {
42
42
  readToolConfig,
43
43
  recordDegradation,
44
44
  recordDegradationOnce
45
- } from "./chunk-N3YQJI6O.js";
45
+ } from "./chunk-JAU72XNY.js";
46
46
  import {
47
47
  logExtension
48
- } from "./chunk-O6TQT6RI.js";
48
+ } from "./chunk-XTMJ7XDT.js";
49
49
  import {
50
50
  logLatency
51
- } from "./chunk-5THXD6X5.js";
51
+ } from "./chunk-QQNQ7SJW.js";
52
52
  import {
53
53
  getProcessSingleton
54
- } from "./chunk-UK3CMEAL.js";
54
+ } from "./chunk-AOHZU2BM.js";
55
55
  import {
56
56
  sweepOwnStagingFiles
57
57
  } from "./chunk-LJDODBBZ.js";
@@ -71,7 +71,7 @@ import {
71
71
  normalizeLoggedPath,
72
72
  normalizeMapKey,
73
73
  toProjectRelativePath
74
- } from "./chunk-Q5U6FMDI.js";
74
+ } from "./chunk-N2H3ZPZY.js";
75
75
  import {
76
76
  __commonJS,
77
77
  __require,
@@ -1744,6 +1744,15 @@ function loadPiLensGlobalConfig(configPath) {
1744
1744
  warnInvalid("actionableWarnings.autoFix.maxFixes must be a non-negative finite number");
1745
1745
  }
1746
1746
  }
1747
+ const contextInjection = asConfigObject(raw.contextInjection);
1748
+ if (contextInjection && "requirePreExistingFixes" in contextInjection) {
1749
+ if (typeof contextInjection.requirePreExistingFixes === "boolean") {
1750
+ config.contextInjection ??= {};
1751
+ config.contextInjection.requirePreExistingFixes = contextInjection.requirePreExistingFixes;
1752
+ } else {
1753
+ warnInvalid("contextInjection.requirePreExistingFixes must be a boolean");
1754
+ }
1755
+ }
1747
1756
  const widget = asConfigObject(raw.widget);
1748
1757
  if (widget) {
1749
1758
  if (typeof widget.visible === "boolean") {
@@ -1876,6 +1885,17 @@ function classifyTmpDir(dir) {
1876
1885
  function ephemeralStagingRoot(filePath) {
1877
1886
  return classifyTmpDir(path6.dirname(path6.resolve(filePath))).stagingRoot;
1878
1887
  }
1888
+ function isPiOwnedTempPath(filePath) {
1889
+ const tmpRoot = realPathOfNearestExisting(os.tmpdir());
1890
+ const real = realPathOfNearestExisting(filePath);
1891
+ if (!isUnderDir(real, tmpRoot))
1892
+ return false;
1893
+ const relative3 = path6.relative(tmpRoot, real);
1894
+ if (relative3.length === 0 || path6.isAbsolute(relative3))
1895
+ return false;
1896
+ const segments = relative3.split(path6.sep);
1897
+ return segments.length === 1 || /^pi-/i.test(segments[0] ?? "");
1898
+ }
1879
1899
  function isEphemeralCheckoutRoot(dir) {
1880
1900
  return classifyTmpDir(dir).checkout;
1881
1901
  }
@@ -1884,14 +1904,14 @@ function isEphemeralCheckoutRoot(dir) {
1884
1904
  function getProjectDataDir(cwd) {
1885
1905
  const legacyProjectDir = path7.join(cwd, ".pi-lens");
1886
1906
  const configuredBase = process.env.PILENS_DATA_DIR?.trim();
1887
- if (!configuredBase && fs4.existsSync(legacyProjectDir)) {
1888
- return legacyProjectDir;
1889
- }
1890
1907
  const resolvedBase = projectDataBase();
1891
1908
  const memoKey = `${resolvedBase}\0${path7.resolve(cwd)}`;
1892
1909
  const cached = settledDataDirs.get(memoKey);
1893
1910
  if (cached !== void 0)
1894
1911
  return cached;
1912
+ if (!configuredBase && fs4.existsSync(legacyProjectDir)) {
1913
+ return legacyProjectDir;
1914
+ }
1895
1915
  const canonical = canonicalProjectRoot(cwd);
1896
1916
  const readable = projectDataDirReadableSlug(canonical.root);
1897
1917
  const hash = projectDataDirRootHash(canonical.root);
@@ -2049,6 +2069,21 @@ function getGlobalPiLensDir() {
2049
2069
  return path7.resolve(override);
2050
2070
  return path7.join(os2.homedir(), ".pi-lens");
2051
2071
  }
2072
+ function isPiLensInternalPath(filePath, projectRoot) {
2073
+ const absolute = path7.resolve(filePath);
2074
+ const home = path7.resolve(os2.homedir());
2075
+ const candidates = [
2076
+ getGlobalPiLensDir(),
2077
+ getProjectDataDir(projectRoot),
2078
+ path7.join(home, ".pi"),
2079
+ path7.join(home, ".pi-lens")
2080
+ ];
2081
+ if (candidates.some((dir) => isUnderDir(absolute, dir)))
2082
+ return true;
2083
+ if (isPiOwnedTempPath(absolute))
2084
+ return true;
2085
+ return false;
2086
+ }
2052
2087
  var EXCLUDED_DIRS = [
2053
2088
  "node_modules",
2054
2089
  ".git",
@@ -3291,6 +3326,39 @@ function mergeInstanceRoots(priorRoots, normalizedRoot) {
3291
3326
  roots.splice(1, 1);
3292
3327
  return roots;
3293
3328
  }
3329
+ var HOST_ROOT_HOLDER = "host";
3330
+ var ROOT_HOLDER_CAP = 2 * INSTANCE_ROOT_CAP;
3331
+ function readRootHolders(entry) {
3332
+ const raw = entry.projectRootHolders;
3333
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
3334
+ return { [HOST_ROOT_HOLDER]: getInstanceRoots(entry) };
3335
+ }
3336
+ const holders = {};
3337
+ for (const [holder, listed] of Object.entries(raw)) {
3338
+ if (!Array.isArray(listed))
3339
+ continue;
3340
+ holders[holder] = listed.filter((root) => typeof root === "string" && root.length > 0);
3341
+ }
3342
+ return holders;
3343
+ }
3344
+ function settleRootHolders(roots, holders) {
3345
+ const primary = roots[0];
3346
+ const settled = {};
3347
+ for (const [holder, listed2] of Object.entries(holders)) {
3348
+ const kept = roots.filter((root) => listed2.includes(root));
3349
+ if (kept.length > 0)
3350
+ settled[holder] = kept;
3351
+ }
3352
+ if (primary !== void 0) {
3353
+ settled[HOST_ROOT_HOLDER] = roots.filter((root) => root === primary || holders[HOST_ROOT_HOLDER]?.includes(root) === true);
3354
+ }
3355
+ const secondaries = Object.keys(settled).filter((holder) => holder !== HOST_ROOT_HOLDER);
3356
+ for (const holder of secondaries.slice(0, Math.max(0, secondaries.length - ROOT_HOLDER_CAP))) {
3357
+ delete settled[holder];
3358
+ }
3359
+ const listed = new Set(Object.values(settled).flat());
3360
+ return { roots: roots.filter((root) => listed.has(root)), holders: settled };
3361
+ }
3294
3362
  function registerInstance(projectRoot) {
3295
3363
  const generation = registrationGeneration().capture();
3296
3364
  return queueRegistryMutation(() => registerInstanceNow(projectRoot, generation));
@@ -3319,14 +3387,23 @@ async function registerInstanceNow(projectRoot, generation) {
3319
3387
  const existing = file.instances.find((entry) => isOwnEntry(entry, selfStart));
3320
3388
  const existingRoots = existing ? getInstanceRoots(existing) : [];
3321
3389
  const roots = existing?.rootSource === "lsp-fallback" ? existingRoots.slice(1).reduce((acc, root) => mergeInstanceRoots(acc, root), [normalizedRoot]) : mergeInstanceRoots(existingRoots, normalizedRoot);
3390
+ const holders = existing ? readRootHolders(existing) : {};
3391
+ const settled = settleRootHolders(roots, {
3392
+ ...holders,
3393
+ [HOST_ROOT_HOLDER]: [
3394
+ ...holders[HOST_ROOT_HOLDER] ?? [],
3395
+ normalizedRoot
3396
+ ]
3397
+ });
3322
3398
  const namespace = ownPidNamespace();
3323
3399
  others.push({
3324
3400
  pid,
3325
3401
  ...selfStart === void 0 ? {} : { processStart: selfStart },
3326
3402
  ...namespace === void 0 ? {} : { pidNamespace: namespace },
3327
3403
  startedAt: existing?.startedAt ?? now,
3328
- projectRoot: roots[0] ?? normalizedRoot,
3329
- projectRoots: roots,
3404
+ projectRoot: settled.roots[0] ?? normalizedRoot,
3405
+ projectRoots: settled.roots,
3406
+ projectRootHolders: settled.holders,
3330
3407
  lspChildren: existing?.lspChildren ?? [],
3331
3408
  lspChildCount: existing?.lspChildren?.length ?? 0,
3332
3409
  rssBytes: process.memoryUsage().rss,
@@ -4550,8 +4627,16 @@ function resolveWindowsCommandForEnvironment(command, cwd, env) {
4550
4627
  function resolveWindowsCommand(command, cwd, env) {
4551
4628
  return resolveWindowsCommandForEnvironment(command, cwd, env);
4552
4629
  }
4553
- function getSpawnEnvironment(overrides) {
4554
- return process.platform === "win32" ? mergeWindowsEnvironment(process.env, overrides) : { ...process.env, ...overrides };
4630
+ function getSpawnEnvironment(overrides, stripNpmConfig) {
4631
+ const merged = process.platform === "win32" ? mergeWindowsEnvironment(process.env, overrides) : { ...process.env, ...overrides };
4632
+ if (!stripNpmConfig)
4633
+ return merged;
4634
+ const stripped = {};
4635
+ for (const [key, value] of Object.entries(merged)) {
4636
+ if (!/^npm_config_/i.test(key))
4637
+ stripped[key] = value;
4638
+ }
4639
+ return stripped;
4555
4640
  }
4556
4641
  var CMD_UNSAFE_CHARS = /["%!\r\n]/;
4557
4642
  function findCmdUnsafeValue(command, args) {
@@ -4744,7 +4829,7 @@ async function safeSpawnAsync(command, args, options) {
4744
4829
  }
4745
4830
  };
4746
4831
  const isWindows2 = process.platform === "win32";
4747
- const spawnEnv = getSpawnEnvironment(options?.env);
4832
+ const spawnEnv = getSpawnEnvironment(options?.env, options?.stripNpmConfig);
4748
4833
  const spawnCwd = isWindows2 ? resolveEffectiveWindowsCwd(options?.cwd, spawnEnv) ?? options?.cwd : options?.cwd;
4749
4834
  let spawnCmd = command;
4750
4835
  let spawnArgs = args;
@@ -5228,7 +5313,7 @@ async function findCommandAsync(command) {
5228
5313
  return result.stdout.trim().split("\n")[0] || null;
5229
5314
  }
5230
5315
  function safeSpawn(command, args, options) {
5231
- const spawnEnv = getSpawnEnvironment(options?.env);
5316
+ const spawnEnv = getSpawnEnvironment(options?.env, options?.stripNpmConfig);
5232
5317
  if (process.platform === "win32") {
5233
5318
  const spawnCwd = resolveEffectiveWindowsCwd(options?.cwd, spawnEnv) ?? options?.cwd;
5234
5319
  const resolved = resolveWindowsCommand(command, options?.cwd, spawnEnv);
@@ -5397,6 +5482,7 @@ export {
5397
5482
  drainProjectDataDirMigrations,
5398
5483
  displayProjectDataPath,
5399
5484
  getGlobalPiLensDir,
5485
+ isPiLensInternalPath,
5400
5486
  EXCLUDED_DIRS,
5401
5487
  getProjectIgnoreMatcher,
5402
5488
  isPathIgnoredByProject,
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  HOOK_WALL_BUDGET_MS,
8
8
  bounded
9
- } from "./chunk-GUOGVTCQ.js";
9
+ } from "./chunk-52FUZI6K.js";
10
10
  import {
11
11
  acquireManagedInstallGate,
12
12
  commitDurableStoreAsync,
@@ -19,38 +19,39 @@ import {
19
19
  refreshManagedTool,
20
20
  resolveManagedNpmBinPath,
21
21
  verifyToolBinary
22
- } from "./chunk-OQGFCZJ4.js";
23
- import "./chunk-RUOG5D2C.js";
22
+ } from "./chunk-66VMUL7Q.js";
23
+ import "./chunk-Q7DUK4LX.js";
24
24
  import {
25
25
  pmBinary,
26
26
  resolveNodePackageManager,
27
27
  updateArgs
28
- } from "./chunk-U3VGR4VU.js";
29
- import "./chunk-NTUJEGDZ.js";
30
- import "./chunk-EOKRQ3SA.js";
31
- import "./chunk-WONERJTP.js";
32
- import "./chunk-22AVIGXS.js";
33
- import "./chunk-GVXA6CCE.js";
34
- import "./chunk-6QIUX4EP.js";
35
- import "./chunk-VHQLPIRJ.js";
28
+ } from "./chunk-AW7R2GWG.js";
29
+ import "./chunk-RWWYJ623.js";
30
+ import "./chunk-VRZP76YM.js";
31
+ import "./chunk-QOBUHWHX.js";
32
+ import "./chunk-QILIYSJF.js";
33
+ import "./chunk-6C7JWPCP.js";
34
+ import "./chunk-5NGR67U5.js";
36
35
  import {
37
36
  safeSpawnAsync
38
- } from "./chunk-VN2AXLEX.js";
37
+ } from "./chunk-C34ZXZ7O.js";
39
38
  import "./chunk-BW5KFIQC.js";
40
39
  import "./chunk-QYF5S6P6.js";
41
- import "./chunk-5ZEJHV35.js";
42
- import "./chunk-DQ2NZ7C4.js";
43
- import "./chunk-VNMT7C64.js";
40
+ import "./chunk-PHDMFAKM.js";
41
+ import "./chunk-2BBLFX75.js";
42
+ import "./chunk-XVF2VVXP.js";
43
+ import "./chunk-ZANLILYD.js";
44
44
  import "./chunk-2EECBNC5.js";
45
45
  import {
46
46
  recordDegradationOnce
47
- } from "./chunk-N3YQJI6O.js";
48
- import "./chunk-O6TQT6RI.js";
49
- import "./chunk-5THXD6X5.js";
50
- import "./chunk-UK3CMEAL.js";
47
+ } from "./chunk-JAU72XNY.js";
48
+ import "./chunk-XTMJ7XDT.js";
49
+ import "./chunk-JMYYOTQG.js";
50
+ import "./chunk-QQNQ7SJW.js";
51
+ import "./chunk-AOHZU2BM.js";
51
52
  import "./chunk-LJDODBBZ.js";
52
53
  import "./chunk-ABBOA7UD.js";
53
- import "./chunk-Q5U6FMDI.js";
54
+ import "./chunk-N2H3ZPZY.js";
54
55
  import "./chunk-NXL4FFQQ.js";
55
56
 
56
57
  // dist/clients/installer/managed-tool-refresh.js
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-ABBOA7UD.js";
5
5
  import {
6
6
  normalizeMapKey
7
- } from "./chunk-Q5U6FMDI.js";
7
+ } from "./chunk-N2H3ZPZY.js";
8
8
 
9
9
  // dist/clients/dispatch/fact-store.js
10
10
  var capacityEvictionReporter;
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
2
2
  import {
3
3
  incrementDegradationCount
4
- } from "./chunk-N3YQJI6O.js";
4
+ } from "./chunk-JAU72XNY.js";
5
5
  import {
6
6
  logLatency
7
- } from "./chunk-5THXD6X5.js";
7
+ } from "./chunk-QQNQ7SJW.js";
8
8
 
9
9
  // dist/clients/bounded-telemetry.js
10
10
  var MAX_TRACKED_TURN_CAPS = 64;
@@ -4,29 +4,32 @@ import {
4
4
  discoverManagedTool,
5
5
  getManagedToolEnvironment,
6
6
  resolveAvailableOrInstall
7
- } from "./chunk-7FBF7NPR.js";
7
+ } from "./chunk-GOYRYZ2R.js";
8
8
  import {
9
9
  mapWithConcurrency
10
10
  } from "./chunk-XIMYZ3JA.js";
11
11
  import {
12
12
  findNodeToolBinary
13
- } from "./chunk-U3VGR4VU.js";
13
+ } from "./chunk-AW7R2GWG.js";
14
+ import {
15
+ getIsolatedNpxSpawnOptions
16
+ } from "./chunk-RWWYJ623.js";
14
17
  import {
15
18
  createAvailabilityLatch
16
- } from "./chunk-WONERJTP.js";
19
+ } from "./chunk-VRZP76YM.js";
17
20
  import {
18
21
  safeSpawnAsync
19
- } from "./chunk-VN2AXLEX.js";
22
+ } from "./chunk-C34ZXZ7O.js";
20
23
  import {
21
24
  compareOrdinal,
22
25
  recordDegradationOnce
23
- } from "./chunk-N3YQJI6O.js";
26
+ } from "./chunk-JAU72XNY.js";
24
27
  import {
25
28
  createSubsystemLogger
26
- } from "./chunk-O6TQT6RI.js";
29
+ } from "./chunk-XTMJ7XDT.js";
27
30
  import {
28
31
  isFullyQualified
29
- } from "./chunk-Q5U6FMDI.js";
32
+ } from "./chunk-N2H3ZPZY.js";
30
33
 
31
34
  // dist/clients/dependency-checker.js
32
35
  import * as fs from "node:fs";
@@ -41,7 +44,12 @@ function buildMadgeArgs(target, projectRoot) {
41
44
  return args;
42
45
  }
43
46
  function parseMadgeCycles(stdout, baseDir, projectRoot) {
44
- const parsed = JSON.parse(stdout || "[]");
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(stdout || "[]");
50
+ } catch (err) {
51
+ throw new Error(`madge report is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
52
+ }
45
53
  const cycles = Array.isArray(parsed) ? parsed : [];
46
54
  const circular = [];
47
55
  const circularFiles = /* @__PURE__ */ new Set();
@@ -446,7 +454,10 @@ var DependencyChecker = class _DependencyChecker {
446
454
  try {
447
455
  const result = await safeSpawnAsync(cmd, [...prefix, ...buildMadgeArgs(normalized, projectRoot)], {
448
456
  timeout: 15e3,
449
- cwd: projectRoot
457
+ // A cache-only npx fallback must not read the project's `.npmrc`
458
+ // (#4268 acceptance 3); a resolved madge keeps the project cwd.
459
+ cwd: projectRoot,
460
+ ...cmd === "npx" ? getIsolatedNpxSpawnOptions() : {}
450
461
  });
451
462
  if (result.error) {
452
463
  this.log(`Check error: ${result.error.message}`);
@@ -661,7 +672,10 @@ var DependencyChecker = class _DependencyChecker {
661
672
  const { cmd, prefix } = await this.resolveMadge(projectRoot);
662
673
  const result = await safeSpawnAsync(cmd, [...prefix, ...buildMadgeArgs(projectRoot, projectRoot)], {
663
674
  timeout: 3e4,
664
- cwd: projectRoot
675
+ // A cache-only npx fallback must not read the project's `.npmrc`
676
+ // (#4268 acceptance 3); a resolved madge keeps the project cwd.
677
+ cwd: projectRoot,
678
+ ...cmd === "npx" ? getIsolatedNpxSpawnOptions() : {}
665
679
  });
666
680
  if (result.error) {
667
681
  this.log(`Scan error: ${result.error.message}`);
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
2
2
  import {
3
3
  detectFileRole
4
- } from "./chunk-DQ2NZ7C4.js";
4
+ } from "./chunk-2BBLFX75.js";
5
5
 
6
6
  // dist/clients/collateral-test-role.js
7
7
  function isTestRoleCollateral(filePath) {