pi-lens 4.4.1 → 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 (138) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/config/dependency-cruiser-eager-allowlist.json +3 -1
  3. package/dist/{chunk-BJF25SUG.js → chunk-23WOO7TX.js} +11 -10
  4. package/dist/{chunk-WATC3IQR.js → chunk-2B73ZPOK.js} +3 -3
  5. package/dist/{chunk-N2IRDBZI.js → chunk-2BBLFX75.js} +101 -11
  6. package/dist/{chunk-TA5L5KWQ.js → chunk-2CD5RS6M.js} +2 -2
  7. package/dist/{chunk-3TTPKMEF.js → chunk-2ZGIZPDG.js} +38 -37
  8. package/dist/{chunk-LNOMA3MP.js → chunk-34WSVGEM.js} +29 -3
  9. package/dist/chunk-3JNKMP3B.js +17 -0
  10. package/dist/{chunk-H2W2AXD3.js → chunk-3UUPUE3O.js} +41 -35
  11. package/dist/{chunk-6P54TMWL.js → chunk-3VPVG5SU.js} +6 -6
  12. package/dist/chunk-3WA4HP4I.js +55 -0
  13. package/dist/chunk-466Z26MG.js +30 -0
  14. package/dist/{chunk-PCHDGUKT.js → chunk-4UNXBNE2.js} +12 -11
  15. package/dist/{chunk-J7WJZ6W7.js → chunk-4W4VLAPJ.js} +12 -11
  16. package/dist/{chunk-F5VLZHUW.js → chunk-52FUZI6K.js} +4 -2
  17. package/dist/chunk-5JM2524W.js +84 -0
  18. package/dist/{chunk-H5EV3VMF.js → chunk-5NGR67U5.js} +2 -2
  19. package/dist/{chunk-YLN4K6WD.js → chunk-66SXUJCA.js} +6 -6
  20. package/dist/{chunk-LD7WFTRX.js → chunk-66VMUL7Q.js} +16 -16
  21. package/dist/{chunk-BHWHXMQ2.js → chunk-67WMNWEE.js} +9 -8
  22. package/dist/{chunk-USHG4DLH.js → chunk-6C7JWPCP.js} +7 -7
  23. package/dist/{chunk-VPWKF3GN.js → chunk-6GFRNVYR.js} +11 -10
  24. package/dist/{chunk-3JL6IFD7.js → chunk-6SDEP3AJ.js} +9 -8
  25. package/dist/{chunk-KJCWXUUS.js → chunk-724UL2TJ.js} +6 -4
  26. package/dist/{chunk-MQA2YBAH.js → chunk-76MWC2K6.js} +3 -3
  27. package/dist/{chunk-XHSCVSOL.js → chunk-7DYBLXYA.js} +3 -3
  28. package/dist/{chunk-AFZYMAIV.js → chunk-7ULNCDCO.js} +37 -35
  29. package/dist/{chunk-VSMJK3ZJ.js → chunk-AOHZU2BM.js} +1 -1
  30. package/dist/{chunk-ZETYB3XG.js → chunk-ARJ6PLFH.js} +44 -28
  31. package/dist/{chunk-T4QZ6FEH.js → chunk-AW7R2GWG.js} +65 -8
  32. package/dist/{chunk-GAYGGICG.js → chunk-BKE7E7TC.js} +10 -9
  33. package/dist/{chunk-EUT3B22Y.js → chunk-BRGDSBJE.js} +13 -12
  34. package/dist/{chunk-T54VJRAD.js → chunk-C34ZXZ7O.js} +55 -11
  35. package/dist/{chunk-CBD2B5CP.js → chunk-CF24OIYI.js} +21 -20
  36. package/dist/{chunk-UGSMCQ4D.js → chunk-CHOW74WE.js} +1 -1
  37. package/dist/{chunk-OZJINN4O.js → chunk-CO2G5PHH.js} +2 -2
  38. package/dist/{chunk-OC7LYAU5.js → chunk-EETY4LF7.js} +24 -10
  39. package/dist/{chunk-KJN4IOEJ.js → chunk-EJIUXPBX.js} +1 -1
  40. package/dist/{chunk-IQZXOZ7S.js → chunk-ESBQHFMJ.js} +549 -271
  41. package/dist/{chunk-CFYISHUW.js → chunk-FLKWCIZH.js} +8 -5
  42. package/dist/{chunk-IUKPRZER.js → chunk-GAEGEPOC.js} +2 -2
  43. package/dist/{chunk-6XX5HCLK.js → chunk-GBPP5P7X.js} +4 -4
  44. package/dist/{chunk-3FERWMCH.js → chunk-GHB6AYCP.js} +27 -26
  45. package/dist/{chunk-NFXP47RV.js → chunk-GOYRYZ2R.js} +26 -24
  46. package/dist/{chunk-TQFBZVCG.js → chunk-GXW6K4YJ.js} +1 -1
  47. package/dist/{chunk-N7YNJE5R.js → chunk-GZYBXISR.js} +9 -9
  48. package/dist/{chunk-3JSEWUWI.js → chunk-IBGIOBEE.js} +3 -3
  49. package/dist/{chunk-OYTMZXRF.js → chunk-IBRALRBR.js} +15 -14
  50. package/dist/{chunk-5JHXUETW.js → chunk-IXXDFY73.js} +3 -3
  51. package/dist/chunk-IZSHAIJ7.js +26 -0
  52. package/dist/{chunk-7ELY2CSM.js → chunk-JAU72XNY.js} +16 -14
  53. package/dist/chunk-JMYYOTQG.js +77 -0
  54. package/dist/{chunk-ELVWJYRV.js → chunk-JSQFTSC6.js} +12 -11
  55. package/dist/{chunk-3P4PF2BX.js → chunk-JWA5I3SR.js} +34 -20
  56. package/dist/{chunk-J6DFZDFA.js → chunk-KBG47GHP.js} +4 -4
  57. package/dist/{chunk-XGUL4SLQ.js → chunk-L3BLXZG7.js} +2 -2
  58. package/dist/chunk-LOP6GRPH.js +31 -0
  59. package/dist/chunk-MQLUAEOC.js +162 -0
  60. package/dist/{chunk-3MRXIJ6I.js → chunk-MRXKYPCS.js} +2 -2
  61. package/dist/{chunk-G3RLJYA2.js → chunk-N2H3ZPZY.js} +47 -1
  62. package/dist/{chunk-HREZQCT3.js → chunk-N3X6Q4YT.js} +3 -3
  63. package/dist/{chunk-NJF2X5XF.js → chunk-NW7BOILN.js} +19 -17
  64. package/dist/{chunk-ZZUFZUQZ.js → chunk-ODBNXWT4.js} +275 -90
  65. package/dist/{chunk-HSIRMK2D.js → chunk-OG5UUPN7.js} +13 -13
  66. package/dist/{chunk-ZOEYVXSV.js → chunk-OXXKQCSV.js} +6 -6
  67. package/dist/{chunk-S6AMWKPC.js → chunk-P7266HLM.js} +2 -2
  68. package/dist/{chunk-JONGANYH.js → chunk-PFNSLWU5.js} +31 -30
  69. package/dist/{chunk-64LU2OVH.js → chunk-PHDMFAKM.js} +12 -2
  70. package/dist/{chunk-IMSQR4WO.js → chunk-PNQDPDRC.js} +1 -1
  71. package/dist/{chunk-MTDRLSI7.js → chunk-PV6LR5P5.js} +5398 -1156
  72. package/dist/{chunk-N77WFUL7.js → chunk-Q6ZWTCLY.js} +24 -22
  73. package/dist/{chunk-IUR76K6A.js → chunk-Q7DUK4LX.js} +5 -5
  74. package/dist/{chunk-CULQYFLU.js → chunk-QGQ5CCCG.js} +2 -2
  75. package/dist/{chunk-UEAHAMEI.js → chunk-QHJ6DQ2R.js} +11 -11
  76. package/dist/{chunk-BNKLYOOO.js → chunk-QILIYSJF.js} +1 -1
  77. package/dist/{chunk-VYKKMYVT.js → chunk-QOBUHWHX.js} +11 -6
  78. package/dist/{chunk-3PNFWVHT.js → chunk-QQNQ7SJW.js} +2 -75
  79. package/dist/{chunk-OEX24ECI.js → chunk-QZVW3AAK.js} +50 -41
  80. package/dist/{chunk-7M4T5N3V.js → chunk-R3PCY3YS.js} +14 -13
  81. package/dist/{chunk-MGIWSROG.js → chunk-RPLINGVB.js} +7 -7
  82. package/dist/{chunk-CMU4RMJB.js → chunk-RWWYJ623.js} +10 -1
  83. package/dist/{chunk-7BX5DWSA.js → chunk-SAEFPSB6.js} +11 -11
  84. package/dist/{chunk-6UYA642J.js → chunk-TYM6OUIT.js} +13 -12
  85. package/dist/{chunk-ALQRYH6O.js → chunk-UXGETRP4.js} +13 -12
  86. package/dist/{chunk-FGALODG3.js → chunk-UZ3TUTRV.js} +1 -1
  87. package/dist/{chunk-J3FZR3YY.js → chunk-VCHXCQFG.js} +3 -3
  88. package/dist/{chunk-DMS52BEP.js → chunk-VITUCP5A.js} +5 -5
  89. package/dist/{chunk-O7HZX7CA.js → chunk-VRZP76YM.js} +1 -1
  90. package/dist/{chunk-VZHJS6DR.js → chunk-VSSBEUFT.js} +16 -15
  91. package/dist/{chunk-U52SAGRM.js → chunk-VWCXW2E7.js} +1 -1
  92. package/dist/{chunk-WW5BLB74.js → chunk-WOA4LN2R.js} +2 -2
  93. package/dist/{chunk-IR6XFA5P.js → chunk-WOKKRCJ5.js} +15 -14
  94. package/dist/{chunk-ZMOMPX2Z.js → chunk-WU567RSC.js} +11 -10
  95. package/dist/{chunk-WSEWKCXU.js → chunk-XCJN5IJU.js} +4 -4
  96. package/dist/{chunk-D65GOCJB.js → chunk-XKIZ2HNN.js} +15 -14
  97. package/dist/{chunk-OYOB3ZFG.js → chunk-XMSXXAHW.js} +2 -2
  98. package/dist/chunk-XPZPXCBV.js +28 -0
  99. package/dist/{chunk-34OCDWOS.js → chunk-XTMJ7XDT.js} +1 -1
  100. package/dist/{chunk-Z6BB4JLQ.js → chunk-XVF2VVXP.js} +5 -3
  101. package/dist/chunk-Z527N6YQ.js +28 -0
  102. package/dist/{chunk-D6YF5HKX.js → chunk-ZANLILYD.js} +22 -2
  103. package/dist/{chunk-2UMYMRI3.js → chunk-ZGDGW2V3.js} +2 -2
  104. package/dist/{chunk-6B5I6ICN.js → chunk-ZHFZWTZV.js} +12 -11
  105. package/dist/{chunk-AXKPQ6ZI.js → chunk-ZXYDQ3TZ.js} +5 -5
  106. package/dist/index.js +72740 -70136
  107. package/dist/mcp/analyze-cli.js +18 -8
  108. package/dist/mcp/cli.js +48 -37
  109. package/dist/mcp/server.js +564 -394
  110. package/dist/mcp/worker.js +66 -55
  111. package/dist/probes/installer.js +20 -19
  112. package/docs/astplayground.md +1 -1
  113. package/docs/configuration.md +29 -0
  114. package/docs/dependencies.md +3 -0
  115. package/docs/features.md +2 -2
  116. package/docs/globalconfig.md +2 -0
  117. package/docs/language-coverage.md +2 -1
  118. package/docs/lsp-capability-matrix.md +29 -7
  119. package/docs/lsp-idle-eviction.md +38 -47
  120. package/docs/pi-lens-fixer.md +4 -0
  121. package/docs/pi-lens-merge-policy.md +5 -0
  122. package/docs/pi-lens-retro.md +2 -1
  123. package/docs/pi-lens-reviewer.md +15 -0
  124. package/docs/pi-lens-subagent.md +2 -0
  125. package/docs/real-harness.md +17 -0
  126. package/docs/schema/pi-lens-config-v1.json +37 -2
  127. package/docs/servercapabilities.md +15 -4
  128. package/docs/settings.md +2 -1
  129. package/package.json +1 -1
  130. package/dist/chunk-2FQ62SPM.js +0 -83
  131. package/dist/chunk-7AXO3ZDF.js +0 -30
  132. package/dist/chunk-KMGPUKFD.js +0 -25
  133. package/dist/chunk-RJFED73B.js +0 -79
  134. package/dist/chunk-RTQNRM5X.js +0 -27
  135. package/dist/chunk-V5MEBST3.js +0 -4139
  136. package/dist/chunk-VGEVL5EQ.js +0 -29
  137. package/dist/chunk-WPE5FPGR.js +0 -54
  138. package/dist/chunk-Z7QQA2KT.js +0 -27
@@ -4,15 +4,15 @@ import {
4
4
  detectPythonEnvironment,
5
5
  detectPythonVenv,
6
6
  pythonEnvironmentToolCandidates
7
- } from "./chunk-LNOMA3MP.js";
7
+ } from "./chunk-34WSVGEM.js";
8
8
  import {
9
9
  resolveOpengrepConfig
10
- } from "./chunk-U52SAGRM.js";
10
+ } from "./chunk-VWCXW2E7.js";
11
11
  import {
12
12
  extensionsForLanguage,
13
13
  getUserRuleRoot,
14
14
  ruleCorpusFingerprintForCycle
15
- } from "./chunk-KJCWXUUS.js";
15
+ } from "./chunk-724UL2TJ.js";
16
16
  import {
17
17
  load,
18
18
  resolvePackagePath
@@ -22,11 +22,11 @@ import {
22
22
  readCargoWorkspaceExclude,
23
23
  readCargoWorkspaceMembers,
24
24
  readTextFileOrUndefined
25
- } from "./chunk-S6AMWKPC.js";
25
+ } from "./chunk-P7266HLM.js";
26
26
  import {
27
27
  HOOK_WALL_BUDGET_MS,
28
28
  bounded
29
- } from "./chunk-F5VLZHUW.js";
29
+ } from "./chunk-52FUZI6K.js";
30
30
  import {
31
31
  ensureTool,
32
32
  findManagedToolBinary,
@@ -36,20 +36,21 @@ import {
36
36
  isZizmorAuditTarget,
37
37
  logSessionStart,
38
38
  resolveZizmorGitHubToken
39
- } from "./chunk-LD7WFTRX.js";
39
+ } from "./chunk-66VMUL7Q.js";
40
40
  import {
41
41
  resolveToolCwd
42
- } from "./chunk-IUR76K6A.js";
42
+ } from "./chunk-Q7DUK4LX.js";
43
43
  import {
44
- findGlobalBinary
45
- } from "./chunk-T4QZ6FEH.js";
44
+ findGlobalBinary,
45
+ isProjectLocalBinPath
46
+ } from "./chunk-AW7R2GWG.js";
46
47
  import {
47
48
  classifyProbeFailure,
48
49
  createAvailabilityLatch,
49
50
  describeInstallAttempt,
50
51
  logAvailabilityDecision,
51
52
  startHostStallSampler
52
- } from "./chunk-O7HZX7CA.js";
53
+ } from "./chunk-VRZP76YM.js";
53
54
  import {
54
55
  OWNER_TAG_ENV,
55
56
  SpawnFailureError,
@@ -63,21 +64,25 @@ import {
63
64
  isCommandAvailableAsync,
64
65
  isPathIgnoredByProject,
65
66
  ownerTagForChildren,
67
+ resolveWindowsCommandForEnvironment,
66
68
  safeSpawnAsync
67
- } from "./chunk-T54VJRAD.js";
69
+ } from "./chunk-C34ZXZ7O.js";
68
70
  import {
69
71
  DOTNET_CSHARP_ROOT_MARKERS,
70
72
  DOTNET_FSHARP_ROOT_MARKERS,
71
- KIND_EXTENSIONS
72
- } from "./chunk-64LU2OVH.js";
73
+ KIND_EXTENSIONS,
74
+ LEAN_ROOT_MARKERS
75
+ } from "./chunk-PHDMFAKM.js";
73
76
  import {
77
+ isRepoTier,
74
78
  lspSectionOf,
75
79
  migrationSubject,
80
+ provenanceFor,
76
81
  reportConfigReadFailure,
77
82
  reportPiLensConfigRecords,
78
83
  resolvePiLensConfig,
79
84
  summarizeConfigResolution
80
- } from "./chunk-N2IRDBZI.js";
85
+ } from "./chunk-2BBLFX75.js";
81
86
  import {
82
87
  FRESHNESS_CADENCE_MS,
83
88
  LSP_NAMESPACE_KEY,
@@ -85,23 +90,30 @@ import {
85
90
  dirMtimesStillFreshAsync,
86
91
  getPiLensGlobalConfigPath,
87
92
  unknownDirMtimeRecords
88
- } from "./chunk-Z6BB4JLQ.js";
93
+ } from "./chunk-XVF2VVXP.js";
89
94
  import {
95
+ getProjectTrustState
96
+ } from "./chunk-ZANLILYD.js";
97
+ import {
98
+ getDegradationLedgerGeneration,
90
99
  incrementDegradationCount,
91
100
  recordDegradationOnce
92
- } from "./chunk-7ELY2CSM.js";
101
+ } from "./chunk-JAU72XNY.js";
102
+ import {
103
+ logExtension
104
+ } from "./chunk-XTMJ7XDT.js";
93
105
  import {
94
106
  claimPhaseOncePerSession,
95
107
  currentSessionRecordId,
96
108
  logLatency,
97
109
  releasePhaseClaim
98
- } from "./chunk-3PNFWVHT.js";
110
+ } from "./chunk-QQNQ7SJW.js";
99
111
  import {
100
112
  getGlobalPiLensLogDir,
101
113
  getProcessSingleton,
102
114
  isTestMode,
103
115
  redactSecrets
104
- } from "./chunk-VSMJK3ZJ.js";
116
+ } from "./chunk-AOHZU2BM.js";
105
117
  import {
106
118
  STAGE_TMP_PATTERN
107
119
  } from "./chunk-LJDODBBZ.js";
@@ -115,6 +127,7 @@ import {
115
127
  findLocalToolConfig,
116
128
  isAtOrAboveHomeDir,
117
129
  isFullyQualified,
130
+ isUnderDir,
118
131
  isWindowsPath,
119
132
  matchesWorkspaceMemberPattern,
120
133
  normalizeEphemeralMapKey,
@@ -122,51 +135,16 @@ import {
122
135
  normalizeMapKey,
123
136
  pathsEqual,
124
137
  toPosix
125
- } from "./chunk-G3RLJYA2.js";
138
+ } from "./chunk-N2H3ZPZY.js";
126
139
  import {
127
140
  __require
128
141
  } from "./chunk-NXL4FFQQ.js";
129
142
 
130
- // dist/clients/lsp/server-traits.js
131
- var ROLE_MEMBERS = {
132
- language: "language",
133
- auxiliary: "auxiliary"
134
- };
135
- var DEFAULT_LSP_SERVER_ROLE = "language";
136
- function isAuxiliary(bearer) {
137
- const declared = bearer?.role;
138
- const role = typeof declared === "string" && Object.hasOwn(ROLE_MEMBERS, declared) ? ROLE_MEMBERS[declared] : DEFAULT_LSP_SERVER_ROLE;
139
- switch (role) {
140
- case "auxiliary":
141
- return true;
142
- case "language":
143
- return false;
144
- }
145
- }
146
- var DEFAULT_NOTIFY_INFLIGHT_LIMIT = 8;
147
- var DEFAULT_REPLY_ORDERING = "unmeasured";
148
- function serverTraits(declaration) {
149
- const declaredLimit = declaration.notifyInflightLimit;
150
- if (typeof declaredLimit === "number" && Number.isFinite(declaredLimit) && declaredLimit > 0) {
151
- return {
152
- role: declaration.role,
153
- notifyInflightLimit: Math.floor(declaredLimit),
154
- replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
155
- };
156
- }
157
- const envLimit = Number(process.env.PI_LENS_LSP_AUX_NOTIFY_INFLIGHT);
158
- return {
159
- role: declaration.role,
160
- notifyInflightLimit: Number.isFinite(envLimit) && envLimit > 0 ? Math.floor(envLimit) : DEFAULT_NOTIFY_INFLIGHT_LIMIT,
161
- replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
162
- };
163
- }
164
-
165
143
  // dist/clients/lsp/server.js
166
144
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3 } from "node:fs";
167
145
  import { access, readFile, readdir, stat } from "node:fs/promises";
168
146
  import os6 from "node:os";
169
- import path7 from "node:path";
147
+ import path6 from "node:path";
170
148
 
171
149
  // dist/clients/sgconfig.js
172
150
  import { createHash } from "node:crypto";
@@ -478,9 +456,44 @@ function findLocalTyposConfig(startDir) {
478
456
  return findLocalToolConfig(startDir, LOCAL_TYPOS_CONFIG_NAMES);
479
457
  }
480
458
 
459
+ // dist/clients/lsp/server-traits.js
460
+ var ROLE_MEMBERS = {
461
+ language: "language",
462
+ auxiliary: "auxiliary"
463
+ };
464
+ var DEFAULT_LSP_SERVER_ROLE = "language";
465
+ function isAuxiliary(bearer) {
466
+ const declared = bearer?.role;
467
+ const role = typeof declared === "string" && Object.hasOwn(ROLE_MEMBERS, declared) ? ROLE_MEMBERS[declared] : DEFAULT_LSP_SERVER_ROLE;
468
+ switch (role) {
469
+ case "auxiliary":
470
+ return true;
471
+ case "language":
472
+ return false;
473
+ }
474
+ }
475
+ var DEFAULT_NOTIFY_INFLIGHT_LIMIT = 8;
476
+ var DEFAULT_REPLY_ORDERING = "unmeasured";
477
+ function serverTraits(declaration) {
478
+ const declaredLimit = declaration.notifyInflightLimit;
479
+ if (typeof declaredLimit === "number" && Number.isFinite(declaredLimit) && declaredLimit > 0) {
480
+ return {
481
+ role: declaration.role,
482
+ notifyInflightLimit: Math.floor(declaredLimit),
483
+ replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
484
+ };
485
+ }
486
+ const envLimit = Number(process.env.PI_LENS_LSP_AUX_NOTIFY_INFLIGHT);
487
+ return {
488
+ role: declaration.role,
489
+ notifyInflightLimit: Number.isFinite(envLimit) && envLimit > 0 ? Math.floor(envLimit) : DEFAULT_NOTIFY_INFLIGHT_LIMIT,
490
+ replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
491
+ };
492
+ }
493
+
481
494
  // dist/clients/lsp/config.js
482
495
  import * as os3 from "node:os";
483
- import path4 from "node:path";
496
+ import path3 from "node:path";
484
497
 
485
498
  // dist/clients/dispatch/known-runner-ids.js
486
499
  var knownRunnerIds = /* @__PURE__ */ new Set();
@@ -495,6 +508,7 @@ function isKnownRunnerId(id) {
495
508
  }
496
509
 
497
510
  // dist/clients/lsp/launch.js
511
+ import { AsyncLocalStorage } from "node:async_hooks";
498
512
  import { execFileSync, spawn as nodeSpawn } from "node:child_process";
499
513
  import fs3 from "node:fs";
500
514
  import os2 from "node:os";
@@ -689,6 +703,16 @@ function isCmdShimValid(cmdPath) {
689
703
  return true;
690
704
  }
691
705
  }
706
+ function isMissingWindowsStartupCommand(command, spawnCommand, cwd, env) {
707
+ if (!isWindows)
708
+ return false;
709
+ if (/\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
710
+ return true;
711
+ }
712
+ if (spawnCommand !== command)
713
+ return false;
714
+ return resolveWindowsCommandForEnvironment(command, cwd, env) === null;
715
+ }
692
716
  function bypassPs1OnWindows(ps1Path, args) {
693
717
  const cmdPath = `${ps1Path.slice(0, -4)}.cmd`;
694
718
  if (fs3.existsSync(cmdPath)) {
@@ -736,6 +760,65 @@ function findBinaryOnPath(command, env) {
736
760
  }
737
761
  return void 0;
738
762
  }
763
+ var lspProjectCodePermission = new AsyncLocalStorage();
764
+ function withLspProjectCodePermission(allowed, spawn) {
765
+ return lspProjectCodePermission.run(allowed, spawn);
766
+ }
767
+ var unknownProjectLocalNoticeGeneration = -1;
768
+ function recordUntrustedLspExecution(request, trust) {
769
+ const generation = getDegradationLedgerGeneration();
770
+ const subject = request.kind === "project-code-server" ? `project-code-server:g${generation}:${request.serverId}:${request.root}` : `project-local-binary:g${generation}:${path2.basename(request.command)}`;
771
+ const metadata = request.kind === "project-code-server" ? {
772
+ field: request.kind,
773
+ serverId: request.serverId,
774
+ root: request.root,
775
+ trust
776
+ } : {
777
+ field: request.kind,
778
+ trust
779
+ };
780
+ recordDegradationOnce({
781
+ kind: "lsp-registry-decision",
782
+ subject,
783
+ reason: (request.kind === "project-local-binary" ? request.reason : void 0) ?? `LSP execution refused: ${request.kind} and project trust is ${trust}`,
784
+ metadata
785
+ });
786
+ if (unknownProjectLocalNoticeGeneration !== generation) {
787
+ unknownProjectLocalNoticeGeneration = generation;
788
+ const label = request.kind === "project-code-server" ? "project-code LSP server" : "project-local LSP binary";
789
+ logExtension({
790
+ subsystem: "lsp-registry",
791
+ level: "warn",
792
+ message: `${label} refused: mark the project trusted in pi or upgrade pi`,
793
+ metadata: { field: request.kind }
794
+ });
795
+ }
796
+ }
797
+ function refuseUntrustedLspExecution(request) {
798
+ const trust = getProjectTrustState();
799
+ const needsTrust = request.kind === "project-code-server" ? trust !== "trusted" : !admitProjectSuppliedTsserver(request.resolvedCommand, request.cwd, true);
800
+ if (!needsTrust)
801
+ return;
802
+ if (request.kind === "project-code-server")
803
+ recordUntrustedLspExecution(request, trust);
804
+ throw new SpawnFailureError("spawn-failed", `LSP ${request.kind === "project-code-server" ? "project-code server" : "project-local binary"} refused: project trust is ${trust}`, new Error(`project trust is ${trust}`));
805
+ }
806
+ function admitProjectSuppliedTsserver(tsserverPath, cwd, projectSupplied, projectCodeAllowed = lspProjectCodePermission.getStore() ?? false) {
807
+ const trust = getProjectTrustState();
808
+ if (tsserverPath && (!projectSupplied || projectCodeAllowed && trust === "trusted"))
809
+ return tsserverPath;
810
+ recordUntrustedLspExecution({
811
+ kind: "project-local-binary",
812
+ command: tsserverPath ?? "tsserver.js",
813
+ resolvedCommand: tsserverPath ?? "tsserver.js",
814
+ cwd,
815
+ reason: tsserverPath ? "LSP execution refused: project compiler requires trusted session ownership" : "LSP execution refused: no admitted absolute TypeScript compiler"
816
+ }, trust);
817
+ return void 0;
818
+ }
819
+ function isProjectLocalLspBinary(resolvedCommand, cwd) {
820
+ return isProjectLocalBinPath(resolvedCommand, cwd);
821
+ }
739
822
  function trySpawn(command, args, cwd, env, needsShell) {
740
823
  let proc;
741
824
  if (needsShell) {
@@ -764,9 +847,6 @@ function trySpawn(command, args, cwd, env, needsShell) {
764
847
  if (!proc.stdin || !proc.stdout || !proc.stderr) {
765
848
  throw new Error(`Failed to spawn LSP server: ${command}`);
766
849
  }
767
- if (proc.exitCode !== null || proc.killed) {
768
- throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`);
769
- }
770
850
  holdOwnChildPid(proc.pid, "lsp-spawn");
771
851
  return proc;
772
852
  }
@@ -842,6 +922,14 @@ async function launchLSP(command, args = [], options = {}) {
842
922
  needsShell = computeNeedsShell(spawnCommand);
843
923
  }
844
924
  }
925
+ if (isProjectLocalLspBinary(spawnCommand, cwd)) {
926
+ refuseUntrustedLspExecution({
927
+ kind: "project-local-binary",
928
+ command,
929
+ resolvedCommand: spawnCommand,
930
+ cwd
931
+ });
932
+ }
845
933
  if (isWindows && /\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
846
934
  logSessionStart2(`lsp cmd-shim-invalid: ${spawnCommand} target missing \u2014 skipping candidate`);
847
935
  const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
@@ -878,7 +966,12 @@ async function launchLSP(command, args = [], options = {}) {
878
966
  throw new Error(`Failed to spawn LSP server: ${command}`);
879
967
  }
880
968
  if (proc.exitCode !== null || proc.killed) {
881
- throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`);
969
+ const message = `LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`;
970
+ const failure = new Error(message);
971
+ if (proc.exitCode === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
972
+ throw new SpawnFailureError("tool-not-found", message, failure);
973
+ }
974
+ throw failure;
882
975
  }
883
976
  logSessionStart2(`lsp launch: command=${command} resolved=${spawnCommand} args=${JSON.stringify(args)} cwd=${cwd} shell=${needsShell ? "true" : "false"} pid=${proc.pid ?? 0}`);
884
977
  const formatStartupStderr = (stderr) => {
@@ -911,7 +1004,13 @@ async function launchLSP(command, args = [], options = {}) {
911
1004
  settled = true;
912
1005
  const isWindowsCmd = isWindows && command.endsWith(".cmd");
913
1006
  const errorMsg = isWindowsCmd && code === 1 ? `npm .cmd shim failed (underlying binary not installed). Run 'npm install' in this project or use a global installation.` : `The binary may be missing or corrupted.`;
914
- reject(new Error(`LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`));
1007
+ const message = `LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`;
1008
+ const failure = new Error(message);
1009
+ if (code === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
1010
+ reject(new SpawnFailureError("tool-not-found", message, failure));
1011
+ return;
1012
+ }
1013
+ reject(failure);
915
1014
  }
916
1015
  });
917
1016
  const startupFailureWindowMs = (() => {
@@ -951,61 +1050,13 @@ async function launchLSP(command, args = [], options = {}) {
951
1050
  };
952
1051
  }
953
1052
 
954
- // dist/clients/lsp/session-roots.js
955
- import path3 from "node:path";
956
- var SESSION_ROOT_CAP = 128;
957
- var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
958
- function noteEvictedRoots(evicted) {
959
- const roots = evicted.map(([root]) => root);
960
- if (roots.length > 0) {
961
- incrementDegradationCount({
962
- kind: "lsp-session-root-evicted",
963
- subject: `cap=${SESSION_ROOT_CAP}`,
964
- reason: `session root registry at capacity; will load the dropped root again on the next session start or tool call naming it (dropped: ${roots[0]})`
965
- });
966
- }
967
- return roots;
968
- }
969
- function registerSessionRoot(cwd) {
970
- const root = path3.resolve(cwd);
971
- if (sessionRoots.has(root))
972
- return [];
973
- return noteEvictedRoots(sessionRoots.set(root, void 0));
974
- }
975
- function setSessionRootConfig(cwd, config) {
976
- return noteEvictedRoots(sessionRoots.set(path3.resolve(cwd), config));
977
- }
978
- function sessionRootConfigEntries() {
979
- return sessionRoots;
980
- }
981
- function isSessionRootRegistered(cwd) {
982
- return sessionRoots.has(path3.resolve(cwd));
983
- }
984
- function shouldInitializeSessionRoot(cwd, readyRoots) {
985
- const normalized = path3.resolve(cwd);
986
- return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
987
- }
988
- function isOutsideAllSessionRoots(filePath) {
989
- if (sessionRoots.size === 0)
990
- return false;
991
- const resolved = path3.resolve(filePath);
992
- for (const root of sessionRoots.keys()) {
993
- if (isSameOrWithin(root, resolved))
994
- return false;
995
- }
996
- return true;
997
- }
998
- function getSessionRootsForTelemetry(limit = 4) {
999
- return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
1000
- }
1001
-
1002
1053
  // dist/clients/lsp/config.js
1003
1054
  function asRecord(value) {
1004
1055
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1005
1056
  }
1006
1057
  var CONFIG_RESOLVED_PHASE = "config_resolved";
1007
1058
  function configResolutionKey(cwd) {
1008
- return normalizeFilePath(path4.resolve(normalizeFilePath(cwd)));
1059
+ return normalizeFilePath(path3.resolve(normalizeFilePath(cwd)));
1009
1060
  }
1010
1061
  function publishConfigResolutionPending(cwd) {
1011
1062
  logSessionStart(`session_start config_resolution_pending session=${currentSessionRecordId()} root=${configResolutionKey(cwd)}`);
@@ -1061,6 +1112,10 @@ async function loadLSPConfig(cwd, homeDir = os3.homedir(), options = {}) {
1061
1112
  });
1062
1113
  const coversProblems = newCoversClaimProblems();
1063
1114
  const config = lspConfigOf(resolution.value, coversProblems);
1115
+ Object.defineProperty(config, "__provenance", {
1116
+ value: resolution.provenance,
1117
+ enumerable: false
1118
+ });
1064
1119
  if (reporting) {
1065
1120
  reportPiLensConfigRecords([
1066
1121
  ...resolution.records,
@@ -1158,7 +1213,7 @@ function customServerSpecsOf(value) {
1158
1213
  const servers = asRecord(lspSectionOf(value).servers);
1159
1214
  return servers ? coversValidatedServers(servers) : {};
1160
1215
  }
1161
- function lspConfigOf(value, problems) {
1216
+ function lspConfigOf(value, problems, provenance) {
1162
1217
  const section = lspSectionOf(value);
1163
1218
  const config = {};
1164
1219
  const servers = asRecord(section.servers);
@@ -1174,6 +1229,12 @@ function lspConfigOf(value, problems) {
1174
1229
  if (Array.isArray(section.warmFiles)) {
1175
1230
  config.warmFiles = section.warmFiles;
1176
1231
  }
1232
+ if (provenance) {
1233
+ Object.defineProperty(config, "__provenance", {
1234
+ value: provenance,
1235
+ enumerable: false
1236
+ });
1237
+ }
1177
1238
  return config;
1178
1239
  }
1179
1240
  function createCustomServer(config, id) {
@@ -1209,26 +1270,74 @@ function createCustomServer(config, id) {
1209
1270
  cwd: root,
1210
1271
  env: config.env ? { ...process.env, ...config.env } : process.env
1211
1272
  });
1212
- return { process: proc };
1273
+ return {
1274
+ process: proc,
1275
+ ...config.initializationOptions ? { initialization: config.initializationOptions } : {}
1276
+ };
1213
1277
  }
1214
1278
  };
1215
1279
  }
1216
1280
  var EMPTY_CONFIG = {
1217
1281
  customServers: [],
1282
+ // Avoid reading LSP_SERVERS during the config/server module cycle. The
1283
+ // selection helper falls back to the live builtin table after evaluation.
1284
+ registeredServers: [],
1218
1285
  disabledServerIds: /* @__PURE__ */ new Set(),
1219
1286
  serverOverrides: /* @__PURE__ */ new Map()
1220
1287
  };
1221
1288
  var configInFlight = /* @__PURE__ */ new Map();
1222
1289
  function normalizeWorkspacePath(cwd) {
1223
- return path4.resolve(cwd);
1290
+ return path3.resolve(cwd);
1291
+ }
1292
+ var unknownTrustNoticeGeneration = -1;
1293
+ function sourceFor(provenance, key) {
1294
+ const direct = provenanceFor({ value: void 0, provenance }, key);
1295
+ if (direct)
1296
+ return direct;
1297
+ let fallback;
1298
+ for (const [candidate, entry] of provenance) {
1299
+ if (!candidate.startsWith(`${key}/`))
1300
+ continue;
1301
+ if (isRepoTier(entry.tier))
1302
+ return entry;
1303
+ fallback ??= entry;
1304
+ }
1305
+ return fallback;
1306
+ }
1307
+ function executableAllowed(provenance, trust) {
1308
+ return !provenance || !isRepoTier(provenance.tier) || trust === "trusted";
1309
+ }
1310
+ function registryDecision(id, field, provenance, trust, allowed) {
1311
+ if (allowed || !provenance || !isRepoTier(provenance.tier))
1312
+ return;
1313
+ const subject = `${id}:${field}:${provenance.tier}`;
1314
+ const reason = `project LSP ${field} refused for ${id}: pi project trust is ${trust}`;
1315
+ recordDegradationOnce({
1316
+ kind: "lsp-registry-decision",
1317
+ subject,
1318
+ reason,
1319
+ metadata: { serverId: id, field, tier: provenance.tier, trust }
1320
+ });
1321
+ if (trust === "unknown") {
1322
+ const generation = getDegradationLedgerGeneration();
1323
+ if (unknownTrustNoticeGeneration !== generation) {
1324
+ unknownTrustNoticeGeneration = generation;
1325
+ logExtension({
1326
+ subsystem: "lsp-registry",
1327
+ level: "warn",
1328
+ message: "project LSP executables refused: mark the project trusted in pi or upgrade pi",
1329
+ metadata: { serverId: id, field }
1330
+ });
1331
+ }
1332
+ }
1224
1333
  }
1225
1334
  function isSameOrChildPath(filePath, candidateRoot) {
1226
1335
  if (filePath === candidateRoot)
1227
1336
  return true;
1228
- return filePath.startsWith(`${candidateRoot}${path4.sep}`);
1337
+ return filePath.startsWith(`${candidateRoot}${path3.sep}`);
1229
1338
  }
1230
1339
  function getConfigForFile(filePath) {
1231
- const resolvedFilePath = path4.resolve(filePath);
1340
+ const resolvedFilePath = path3.resolve(filePath);
1232
1341
  let bestMatch;
1233
1342
  for (const [root, config] of sessionRootConfigEntries()) {
1234
1343
  if (config === void 0)
@@ -1242,13 +1351,33 @@ function getConfigForFile(filePath) {
1242
1351
  return bestMatch?.config ?? EMPTY_CONFIG;
1243
1352
  }
1244
1353
  function registerLSPConfig(config) {
1354
+ return compileLspRegistry(config, config.__provenance);
1355
+ }
1356
+ function compileLspRegistry(config, provenance = /* @__PURE__ */ new Map()) {
1357
+ const trust = getProjectTrustState();
1245
1358
  const customServers = [];
1246
1359
  const disabledServerIds = new Set(config.disabledServers ?? []);
1247
1360
  if (config.servers) {
1248
1361
  for (const [id, serverConfig] of Object.entries(config.servers)) {
1362
+ const commandSource = sourceFor(provenance, `/lsp/servers/${id}/command`);
1363
+ const commandAllowed = executableAllowed(commandSource, trust);
1364
+ registryDecision(id, "command", commandSource, trust, commandAllowed);
1365
+ if (!commandAllowed)
1366
+ continue;
1367
+ const envSource = sourceFor(provenance, `/lsp/servers/${id}/env`);
1368
+ const initSource = sourceFor(provenance, `/lsp/servers/${id}/initializationOptions`);
1369
+ const envAllowed = executableAllowed(envSource, trust);
1370
+ const initAllowed = executableAllowed(initSource, trust);
1371
+ registryDecision(id, "env", envSource, trust, envAllowed);
1372
+ registryDecision(id, "initializationOptions", initSource, trust, initAllowed);
1373
+ const admitted = { ...serverConfig };
1374
+ if (!envAllowed)
1375
+ delete admitted.env;
1376
+ if (!initAllowed)
1377
+ delete admitted.initializationOptions;
1249
1378
  try {
1250
- const server = createCustomServer(serverConfig, id);
1251
- customServers.push(server);
1379
+ const server = createCustomServer(admitted, id);
1380
+ customServers.push({ ...server, trustAllowed: true });
1252
1381
  } catch {
1253
1382
  }
1254
1383
  }
@@ -1258,15 +1387,53 @@ function registerLSPConfig(config) {
1258
1387
  for (const [id, entry] of Object.entries(config.serverOverrides)) {
1259
1388
  if (entry && typeof entry === "object" && !Array.isArray(entry)) {
1260
1389
  const initOpts = entry.initializationOptions;
1261
- if (initOpts !== void 0 && typeof initOpts === "object" && initOpts !== null && !Array.isArray(initOpts)) {
1390
+ const command = entry.command;
1391
+ const commandSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/command`);
1392
+ const envSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/env`);
1393
+ const initSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/initializationOptions`);
1394
+ const commandAllowed = executableAllowed(commandSource, trust);
1395
+ const envAllowed = executableAllowed(envSource, trust);
1396
+ const overrideInitAllowed = executableAllowed(initSource, trust);
1397
+ registryDecision(id, "command override", commandSource, trust, commandAllowed);
1398
+ registryDecision(id, "env override", envSource, trust, envAllowed);
1399
+ registryDecision(id, "initializationOptions", initSource, trust, overrideInitAllowed);
1400
+ if (command !== void 0 || entry.env !== void 0 || initOpts !== void 0 && typeof initOpts === "object" && initOpts !== null && !Array.isArray(initOpts)) {
1262
1401
  serverOverrides.set(id, {
1263
- initializationOptions: initOpts
1402
+ ...overrideInitAllowed && initOpts !== void 0 ? { initializationOptions: initOpts } : {},
1403
+ ...commandAllowed && command !== void 0 ? { command } : {},
1404
+ ...envAllowed && entry.env ? { env: entry.env } : {}
1264
1405
  });
1265
1406
  }
1266
1407
  }
1267
1408
  }
1268
1409
  }
1269
- return { customServers, disabledServerIds, serverOverrides };
1410
+ const overriddenBuiltins = LSP_SERVERS.map((server) => {
1411
+ const override = serverOverrides.get(server.id);
1412
+ if (!override?.command)
1413
+ return { ...server };
1414
+ const argv = Array.isArray(override.command) ? override.command : [override.command, "--stdio"];
1415
+ return {
1416
+ ...server,
1417
+ trustAllowed: true,
1418
+ async spawn(root, options) {
1419
+ void options;
1420
+ const program = argv[0];
1421
+ if (!program)
1422
+ throw new Error(`empty command override for ${server.id}`);
1423
+ const proc = await launchLSP(program, argv.slice(1), {
1424
+ cwd: root,
1425
+ env: override.env ? { ...process.env, ...override.env } : process.env
1426
+ });
1427
+ return { process: proc };
1428
+ }
1429
+ };
1430
+ });
1431
+ return {
1432
+ customServers,
1433
+ registeredServers: overriddenBuiltins,
1434
+ disabledServerIds,
1435
+ serverOverrides
1436
+ };
1270
1437
  }
1271
1438
  function forgetConfigResolvedClaims(evictedRoots) {
1272
1439
  for (const root of evictedRoots) {
@@ -1293,7 +1460,8 @@ async function initLSPConfig(cwd) {
1293
1460
  }
1294
1461
  }
1295
1462
  function registeredServers(config) {
1296
- return [...LSP_SERVERS, ...config.customServers];
1463
+ const builtins = config.registeredServers.length ? config.registeredServers : LSP_SERVERS;
1464
+ return [...builtins, ...config.customServers];
1297
1465
  }
1298
1466
  function selectionReason(server, config, filePath, ext, base) {
1299
1467
  if (config.disabledServerIds.has(server.id))
@@ -1313,8 +1481,8 @@ function selectionReason(server, config, filePath, ext, base) {
1313
1481
  return "selected";
1314
1482
  }
1315
1483
  function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
1316
- const ext = path4.extname(filePath).toLowerCase();
1317
- const base = path4.basename(filePath).toLowerCase();
1484
+ const ext = path3.extname(filePath).toLowerCase();
1485
+ const base = path3.basename(filePath).toLowerCase();
1318
1486
  return registeredServers(config).map((server) => {
1319
1487
  const reason = selectionReason(server, config, filePath, ext, base);
1320
1488
  return { server, selected: reason === "selected", reason };
@@ -1322,8 +1490,8 @@ function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
1322
1490
  }
1323
1491
  function getServersForFileWithConfig(filePath) {
1324
1492
  const config = getConfigForFile(filePath);
1325
- const ext = path4.extname(filePath).toLowerCase();
1326
- const base = path4.basename(filePath).toLowerCase();
1493
+ const ext = path3.extname(filePath).toLowerCase();
1494
+ const base = path3.basename(filePath).toLowerCase();
1327
1495
  return registeredServers(config).filter((server) => selectionReason(server, config, filePath, ext, base) === "selected");
1328
1496
  }
1329
1497
  function primaryServerEntry(filePath) {
@@ -1384,11 +1552,15 @@ function resolveAstGrepNativeExe(platform = process.platform, arch = process.arc
1384
1552
  }
1385
1553
  var SERVER_DIAGNOSTIC_STRATEGIES = {
1386
1554
  typescript: {
1387
- seedFirstPush: true,
1555
+ seedFirstPush: false,
1388
1556
  pullRetryBudgetMs: 0,
1389
1557
  debounceMs: 50,
1390
1558
  aggregateWaitMs: 1e3,
1391
1559
  expectSemanticSecondPush: false,
1560
+ // #3310 / nightly run 37930006227: the clean TypeScript fixture
1561
+ // published an empty pre-index result before its settled result.
1562
+ // Hold that first publish so it cannot resolve a push wait as clean.
1563
+ emptyFirstPublish: "indexing",
1392
1564
  // Tier 3 (#458): typescript-language-server publishes nothing on a
1393
1565
  // clean→clean edit (docs/lsp-capability-matrix.md, re-confirmed
1394
1566
  // 2026-07-12). It's the lone core-set tier-3 server, which is exactly
@@ -1790,14 +1962,14 @@ function classifyCascadeWaitTier(lspService, filePath, snapshots) {
1790
1962
  // dist/clients/lsp/lombok.js
1791
1963
  import * as fs4 from "node:fs";
1792
1964
  import * as os4 from "node:os";
1793
- import * as path5 from "node:path";
1965
+ import * as path4 from "node:path";
1794
1966
  var LOMBOK_ENV_KEYS = ["PI_LENS_LOMBOK_JAR", "LOMBOK_JAR"];
1795
1967
  var LOMBOK_PROJECT_FILES = [
1796
1968
  "lombok.config",
1797
1969
  "pom.xml",
1798
1970
  "build.gradle",
1799
1971
  "build.gradle.kts",
1800
- path5.join("gradle", "libs.versions.toml")
1972
+ path4.join("gradle", "libs.versions.toml")
1801
1973
  ];
1802
1974
  function fileExists(filePath) {
1803
1975
  if (!filePath)
@@ -1822,13 +1994,13 @@ function containsLombokDependency(text) {
1822
1994
  return /\borg\.projectlombok\b/i.test(text) || /<artifactId>\s*lombok\s*<\/artifactId>/i.test(text) || /\b(annotationProcessor|compileOnly|testCompileOnly|testAnnotationProcessor)\b[^\n]*\blombok\b/i.test(text);
1823
1995
  }
1824
1996
  function hasLombokProject(root) {
1825
- const lombokConfig = path5.join(root, "lombok.config");
1997
+ const lombokConfig = path4.join(root, "lombok.config");
1826
1998
  if (fileExists(lombokConfig))
1827
1999
  return true;
1828
2000
  for (const name of LOMBOK_PROJECT_FILES) {
1829
2001
  if (name === "lombok.config")
1830
2002
  continue;
1831
- const text = readTextIfSmall(path5.join(root, name));
2003
+ const text = readTextIfSmall(path4.join(root, name));
1832
2004
  if (text && containsLombokDependency(text))
1833
2005
  return true;
1834
2006
  }
@@ -1838,16 +2010,16 @@ function envJarCandidate(env) {
1838
2010
  for (const key of LOMBOK_ENV_KEYS) {
1839
2011
  const value = env[key]?.trim();
1840
2012
  if (fileExists(value))
1841
- return path5.resolve(value);
2013
+ return path4.resolve(value);
1842
2014
  }
1843
2015
  return void 0;
1844
2016
  }
1845
2017
  function localJarCandidates(root) {
1846
2018
  return [
1847
- path5.join(root, "lombok.jar"),
1848
- path5.join(root, ".lombok", "lombok.jar"),
1849
- path5.join(root, "lib", "lombok.jar"),
1850
- path5.join(root, "libs", "lombok.jar")
2019
+ path4.join(root, "lombok.jar"),
2020
+ path4.join(root, ".lombok", "lombok.jar"),
2021
+ path4.join(root, "lib", "lombok.jar"),
2022
+ path4.join(root, "libs", "lombok.jar")
1851
2023
  ];
1852
2024
  }
1853
2025
  function newestExistingJar(candidates) {
@@ -1866,17 +2038,17 @@ function newestExistingJar(candidates) {
1866
2038
  return best?.filePath;
1867
2039
  }
1868
2040
  function mavenLocalLombokJar(home = os4.homedir()) {
1869
- const base = path5.join(home, ".m2", "repository", "org", "projectlombok", "lombok");
2041
+ const base = path4.join(home, ".m2", "repository", "org", "projectlombok", "lombok");
1870
2042
  let versions = [];
1871
2043
  try {
1872
2044
  versions = fs4.readdirSync(base);
1873
2045
  } catch {
1874
2046
  return void 0;
1875
2047
  }
1876
- return newestExistingJar(versions.map((version) => path5.join(base, version, `lombok-${version}.jar`)));
2048
+ return newestExistingJar(versions.map((version) => path4.join(base, version, `lombok-${version}.jar`)));
1877
2049
  }
1878
2050
  function gradleCacheLombokJar(home = os4.homedir()) {
1879
- const base = path5.join(home, ".gradle", "caches", "modules-2", "files-2.1", "org.projectlombok", "lombok");
2051
+ const base = path4.join(home, ".gradle", "caches", "modules-2", "files-2.1", "org.projectlombok", "lombok");
1880
2052
  const candidates = [];
1881
2053
  let versions = [];
1882
2054
  try {
@@ -1885,7 +2057,7 @@ function gradleCacheLombokJar(home = os4.homedir()) {
1885
2057
  return void 0;
1886
2058
  }
1887
2059
  for (const version of versions) {
1888
- const versionDir = path5.join(base, version);
2060
+ const versionDir = path4.join(base, version);
1889
2061
  let hashes = [];
1890
2062
  try {
1891
2063
  hashes = fs4.readdirSync(versionDir);
@@ -1893,7 +2065,7 @@ function gradleCacheLombokJar(home = os4.homedir()) {
1893
2065
  continue;
1894
2066
  }
1895
2067
  for (const hash of hashes) {
1896
- candidates.push(path5.join(versionDir, hash, `lombok-${version}.jar`));
2068
+ candidates.push(path4.join(versionDir, hash, `lombok-${version}.jar`));
1897
2069
  }
1898
2070
  }
1899
2071
  return newestExistingJar(candidates);
@@ -1926,15 +2098,15 @@ function createLombokJdtlsArgs(root, baseEnv = process.env) {
1926
2098
  // dist/clients/lsp/jvm-runtime.js
1927
2099
  import { existsSync as existsSync2, readdirSync as readdirSync4 } from "node:fs";
1928
2100
  import os5 from "node:os";
1929
- import path6 from "node:path";
2101
+ import path5 from "node:path";
1930
2102
  var JAVA_EXE = process.platform === "win32" ? "java.exe" : "java";
1931
2103
  var JAVA_PROBE_TIMEOUT_MS = 5e3;
1932
2104
  var MIN_JAVA_MAJOR = 17;
1933
2105
  function jdkHomeFrom(dir) {
1934
- if (existsSync2(path6.join(dir, "bin", JAVA_EXE)))
2106
+ if (existsSync2(path5.join(dir, "bin", JAVA_EXE)))
1935
2107
  return dir;
1936
- const macHome = path6.join(dir, "Contents", "Home");
1937
- if (existsSync2(path6.join(macHome, "bin", JAVA_EXE)))
2108
+ const macHome = path5.join(dir, "Contents", "Home");
2109
+ if (existsSync2(path5.join(macHome, "bin", JAVA_EXE)))
1938
2110
  return macHome;
1939
2111
  return void 0;
1940
2112
  }
@@ -1947,7 +2119,7 @@ function parseMajorVersion(name) {
1947
2119
  }
1948
2120
  function childDirs(base) {
1949
2121
  try {
1950
- return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => path6.join(base, e.name));
2122
+ return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => path5.join(base, e.name));
1951
2123
  } catch {
1952
2124
  return [];
1953
2125
  }
@@ -1955,26 +2127,26 @@ function childDirs(base) {
1955
2127
  function candidateRoots() {
1956
2128
  const home = os5.homedir();
1957
2129
  const roots = [];
1958
- roots.push(path6.join(home, ".jdks"));
1959
- roots.push(path6.join(getGlobalPiLensDir(), "tools"));
2130
+ roots.push(path5.join(home, ".jdks"));
2131
+ roots.push(path5.join(getGlobalPiLensDir(), "tools"));
1960
2132
  if (process.platform === "win32") {
1961
2133
  const progFiles = [
1962
2134
  process.env.ProgramFiles,
1963
2135
  process.env["ProgramFiles(x86)"],
1964
2136
  process.env.ProgramW6432,
1965
- path6.join(process.env.LOCALAPPDATA ?? path6.join(home, "AppData", "Local"), "Programs")
2137
+ path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "Programs")
1966
2138
  ].filter((p) => Boolean(p));
1967
2139
  for (const base of progFiles) {
1968
- roots.push(path6.join(base, "Eclipse Adoptium"));
1969
- roots.push(path6.join(base, "Java"));
1970
- roots.push(path6.join(base, "Microsoft"));
1971
- roots.push(path6.join(base, "Zulu"));
1972
- roots.push(path6.join(base, "Amazon Corretto"));
1973
- roots.push(path6.join(base, "BellSoft"));
2140
+ roots.push(path5.join(base, "Eclipse Adoptium"));
2141
+ roots.push(path5.join(base, "Java"));
2142
+ roots.push(path5.join(base, "Microsoft"));
2143
+ roots.push(path5.join(base, "Zulu"));
2144
+ roots.push(path5.join(base, "Amazon Corretto"));
2145
+ roots.push(path5.join(base, "BellSoft"));
1974
2146
  }
1975
2147
  } else if (process.platform === "darwin") {
1976
2148
  roots.push("/Library/Java/JavaVirtualMachines");
1977
- roots.push(path6.join(home, "Library", "Java", "JavaVirtualMachines"));
2149
+ roots.push(path5.join(home, "Library", "Java", "JavaVirtualMachines"));
1978
2150
  roots.push("/opt/homebrew/opt");
1979
2151
  roots.push("/usr/local/opt");
1980
2152
  } else {
@@ -1998,7 +2170,7 @@ function discoverJdkHome(roots = candidateRoots(), javaHome = process.env.JAVA_H
1998
2170
  continue;
1999
2171
  found.push({
2000
2172
  home: resolved,
2001
- major: parseMajorVersion(path6.basename(dir))
2173
+ major: parseMajorVersion(path5.basename(dir))
2002
2174
  });
2003
2175
  }
2004
2176
  }
@@ -2097,12 +2269,12 @@ async function resolveJavaRuntimeEnv() {
2097
2269
  }
2098
2270
  const home = discoverJdkHome();
2099
2271
  if (home) {
2100
- const binDir = path6.join(home, "bin");
2272
+ const binDir = path5.join(home, "bin");
2101
2273
  const currentPath = process.env.PATH ?? process.env.Path ?? "";
2102
2274
  _cachedEnv = {
2103
2275
  value: {
2104
2276
  JAVA_HOME: home,
2105
- PATH: binDir + path6.delimiter + currentPath
2277
+ PATH: binDir + path5.delimiter + currentPath
2106
2278
  }
2107
2279
  };
2108
2280
  return _cachedEnv.value;
@@ -2158,7 +2330,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
2158
2330
  rootFailed = true;
2159
2331
  onRootFailure?.(reason);
2160
2332
  }
2161
- const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length && path7.resolve(serverRoot) === path7.resolve(path7.dirname(filePath));
2333
+ const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length && path6.resolve(serverRoot) === path6.resolve(path6.dirname(filePath));
2162
2334
  if (!serverRoot || isFileDirFallback) {
2163
2335
  const probedMarker = onRootFallback && !rootFailed && rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
2164
2336
  cwd: sessionCwd,
@@ -2167,7 +2339,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
2167
2339
  }).marker : void 0;
2168
2340
  const refusedMarker = probedMarker !== void 0 && rootMarkers?.includes(probedMarker) ? probedMarker : void 0;
2169
2341
  const fallbackCwd = rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
2170
- cwd: path7.dirname(path7.resolve(filePath)),
2342
+ cwd: path6.dirname(path6.resolve(filePath)),
2171
2343
  rootMarkers
2172
2344
  }) : void 0;
2173
2345
  if (!serverRoot) {
@@ -2237,17 +2409,17 @@ var PROJECT_BOUNDARY_MARKERS = [
2237
2409
  var loggedRootCeilingClamps = /* @__PURE__ */ new Set();
2238
2410
  var posixCaseInsensitiveByPath = /* @__PURE__ */ new Map();
2239
2411
  function posixFilesystemIsCaseInsensitive(root) {
2240
- const resolved = path7.resolve(root);
2412
+ const resolved = path6.resolve(root);
2241
2413
  const cached = posixCaseInsensitiveByPath.get(resolved);
2242
2414
  if (cached !== void 0)
2243
2415
  return cached;
2244
2416
  if (!existsSync3(resolved)) {
2245
2417
  return false;
2246
2418
  }
2247
- const name = path7.basename(resolved);
2419
+ const name = path6.basename(resolved);
2248
2420
  const alternate = name.toLowerCase() === name ? name.toUpperCase() : name.toLowerCase();
2249
2421
  let insensitive = false;
2250
- const alternatePath = path7.join(path7.dirname(resolved), alternate);
2422
+ const alternatePath = path6.join(path6.dirname(resolved), alternate);
2251
2423
  if (alternate !== name && existsSync3(alternatePath)) {
2252
2424
  try {
2253
2425
  const actual = statSync3(resolved);
@@ -2265,7 +2437,7 @@ function resetLSPCaseSensitivityState() {
2265
2437
  }
2266
2438
  function isSameOrWithin(ancestor, candidate, deps = {}) {
2267
2439
  const windowsShaped = isWindowsPath(ancestor) || isWindowsPath(candidate);
2268
- const pathApi = windowsShaped ? path7.win32 : path7;
2440
+ const pathApi = windowsShaped ? path6.win32 : path6;
2269
2441
  const resolvedAncestor = pathApi.resolve(ancestor);
2270
2442
  const resolvedCandidate = pathApi.resolve(candidate);
2271
2443
  let caseInsensitive = false;
@@ -2285,7 +2457,7 @@ function isSameOrWithin(ancestor, candidate, deps = {}) {
2285
2457
  }
2286
2458
  function enforceLspRootCeiling(root, sessionCwd, filePath) {
2287
2459
  const windowsShaped = isWindowsPath(root) || isWindowsPath(sessionCwd);
2288
- const pathApi = windowsShaped ? path7.win32 : path7;
2460
+ const pathApi = windowsShaped ? path6.win32 : path6;
2289
2461
  const resolvedRoot = pathApi.resolve(root);
2290
2462
  const resolvedCwd = pathApi.resolve(sessionCwd);
2291
2463
  if (filePath && !isSameOrWithin(resolvedCwd, pathApi.resolve(filePath))) {
@@ -2310,8 +2482,8 @@ async function hasProjectBoundaryMarker(dir) {
2310
2482
  return false;
2311
2483
  }
2312
2484
  function pathSegments(dir) {
2313
- const parsed = path7.parse(path7.resolve(dir));
2314
- return path7.relative(parsed.root, path7.resolve(dir)).split(path7.sep).filter(Boolean).map((segment) => segment.toLowerCase());
2485
+ const parsed = path6.parse(path6.resolve(dir));
2486
+ return path6.relative(parsed.root, path6.resolve(dir)).split(path6.sep).filter(Boolean).map((segment) => segment.toLowerCase());
2315
2487
  }
2316
2488
  function hasFixtureConvention(dir) {
2317
2489
  const segments = pathSegments(dir);
@@ -2323,18 +2495,18 @@ function hasAtomicStageSegment(dir) {
2323
2495
  return pathSegments(dir).some((segment) => STAGE_TMP_PATTERN.test(segment));
2324
2496
  }
2325
2497
  async function findGitBoundary(dir) {
2326
- let current = path7.resolve(dir);
2327
- const fsRoot = path7.parse(current).root;
2498
+ let current = path6.resolve(dir);
2499
+ const fsRoot = path6.parse(current).root;
2328
2500
  while (true) {
2329
2501
  if (await markerExists(current, ".git"))
2330
2502
  return current;
2331
2503
  if (current === fsRoot)
2332
2504
  return void 0;
2333
- current = path7.dirname(current);
2505
+ current = path6.dirname(current);
2334
2506
  }
2335
2507
  }
2336
2508
  async function isExcludedLspRoot(dir) {
2337
- const candidate = path7.resolve(dir);
2509
+ const candidate = path6.resolve(dir);
2338
2510
  if (hasFixtureConvention(candidate) || hasAtomicStageSegment(candidate))
2339
2511
  return true;
2340
2512
  const gitRoot = await findGitBoundary(candidate);
@@ -2346,9 +2518,9 @@ async function isExcludedLspRoot(dir) {
2346
2518
  }
2347
2519
  async function nearestNonExcludedFallbackRoot(candidate) {
2348
2520
  if (!await isExcludedLspRoot(candidate))
2349
- return path7.resolve(candidate);
2350
- let current = path7.dirname(path7.resolve(candidate));
2351
- const fsRoot = path7.parse(current).root;
2521
+ return path6.resolve(candidate);
2522
+ let current = path6.dirname(path6.resolve(candidate));
2523
+ const fsRoot = path6.parse(current).root;
2352
2524
  let nearestAllowed;
2353
2525
  while (true) {
2354
2526
  if (!await isExcludedLspRoot(current)) {
@@ -2360,7 +2532,7 @@ async function nearestNonExcludedFallbackRoot(candidate) {
2360
2532
  }
2361
2533
  if (current === fsRoot)
2362
2534
  break;
2363
- current = path7.dirname(current);
2535
+ current = path6.dirname(current);
2364
2536
  }
2365
2537
  return nearestAllowed ?? fsRoot;
2366
2538
  }
@@ -2401,7 +2573,7 @@ async function installEvidenceForLaunch(toolId, installed, attempt) {
2401
2573
  const confirmedManagedPath = await findManagedToolBinary(toolId);
2402
2574
  return {
2403
2575
  ...evidence,
2404
- binary: path7.basename(installed),
2576
+ binary: path6.basename(installed),
2405
2577
  ...confirmedManagedPath !== void 0 && pathsEqual(confirmedManagedPath, installed) && {
2406
2578
  source: "managed-dir"
2407
2579
  }
@@ -2454,7 +2626,7 @@ function markDirectLspCommandUnavailable(command) {
2454
2626
  directLspCommandUnavailableUntil.set(command, Date.now() + DIRECT_LSP_NEGATIVE_TTL_MS);
2455
2627
  directLspCommandSkipLoggedUntil.delete(command);
2456
2628
  }
2457
- var PI_LENS_BIN_DIR2 = path7.join(getGlobalPiLensDir(), "bin");
2629
+ var PI_LENS_BIN_DIR2 = path6.join(getGlobalPiLensDir(), "bin");
2458
2630
  async function resolveAndLaunch(spec, allowInstall) {
2459
2631
  const generation = lspLaunchAvailabilityGeneration.capture();
2460
2632
  const toolLabel = spec.managedToolId ?? spec.candidates[spec.candidates.length - 1] ?? "unknown";
@@ -2519,7 +2691,7 @@ async function resolveAndLaunch(spec, allowInstall) {
2519
2691
  producer: "lsp-launch",
2520
2692
  classifiedBy: "probe",
2521
2693
  evidence: {
2522
- binary: path7.basename(managedCandidate),
2694
+ binary: path6.basename(managedCandidate),
2523
2695
  source: "managed-dir",
2524
2696
  correctsLatchedRow: false
2525
2697
  }
@@ -2812,7 +2984,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
2812
2984
  return void 0;
2813
2985
  }
2814
2986
  const suffix = process.platform === "win32" ? ".exe" : "";
2815
- const binPath = path7.join(bundleDir, ...spec.binRelPath.split("/")) + suffix;
2987
+ const binPath = path6.join(bundleDir, ...spec.binRelPath.split("/")) + suffix;
2816
2988
  try {
2817
2989
  const proc = await launchLSP(binPath, spec.args, {
2818
2990
  cwd: spec.cwd,
@@ -2827,7 +2999,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
2827
2999
  }
2828
3000
  }
2829
3001
  function nodeBinLocalCandidates(root, baseName) {
2830
- const localBase = path7.join(root, "node_modules", ".bin", baseName);
3002
+ const localBase = path6.join(root, "node_modules", ".bin", baseName);
2831
3003
  if (process.platform === "win32") {
2832
3004
  return [`${localBase}.cmd`, `${localBase}.exe`];
2833
3005
  }
@@ -2837,7 +3009,7 @@ function nodeBinCandidates(root, baseName) {
2837
3009
  return [...nodeBinLocalCandidates(root, baseName), baseName];
2838
3010
  }
2839
3011
  function piAgentExtensionsRootKey(file) {
2840
- const dirKey = normalizeEphemeralMapKey(path7.dirname(path7.resolve(file)));
3012
+ const dirKey = normalizeEphemeralMapKey(path6.dirname(path6.resolve(file)));
2841
3013
  const marker = "/.pi/agent/extensions";
2842
3014
  const index = dirKey.indexOf(marker);
2843
3015
  if (index === -1)
@@ -2845,12 +3017,12 @@ function piAgentExtensionsRootKey(file) {
2845
3017
  return dirKey.slice(0, index + marker.length);
2846
3018
  }
2847
3019
  function IgnoreHomeRoot(primary) {
2848
- const homeKey = normalizeEphemeralMapKey(path7.resolve(os6.homedir()));
3020
+ const homeKey = normalizeEphemeralMapKey(path6.resolve(os6.homedir()));
2849
3021
  return withRootMarkers(async (file) => {
2850
3022
  const root = await primary(file);
2851
3023
  if (!root)
2852
3024
  return void 0;
2853
- return normalizeEphemeralMapKey(path7.resolve(root)) === homeKey ? void 0 : root;
3025
+ return normalizeEphemeralMapKey(path6.resolve(root)) === homeKey ? void 0 : root;
2854
3026
  }, primary.rootMarkers ?? []);
2855
3027
  }
2856
3028
  function rubyBinCandidates(baseName) {
@@ -2858,13 +3030,13 @@ function rubyBinCandidates(baseName) {
2858
3030
  const home = os6.homedir();
2859
3031
  const isWin = process.platform === "win32";
2860
3032
  const ext = isWin ? ".bat" : "";
2861
- candidates.push(path7.join(home, ".local", "share", "mise", "installs", "ruby", "bin", `${baseName}${ext}`));
2862
- candidates.push(path7.join(home, ".asdf", "installs", "ruby", "bin", `${baseName}${ext}`));
3033
+ candidates.push(path6.join(home, ".local", "share", "mise", "installs", "ruby", "bin", `${baseName}${ext}`));
3034
+ candidates.push(path6.join(home, ".asdf", "installs", "ruby", "bin", `${baseName}${ext}`));
2863
3035
  if (isWin) {
2864
- const driveRoot = path7.parse(home).root;
3036
+ const driveRoot = path6.parse(home).root;
2865
3037
  for (const entry of getRubyVersionDirNamesSync(driveRoot)) {
2866
- candidates.push(path7.join(driveRoot, entry, "bin", `${baseName}.bat`));
2867
- candidates.push(path7.join(driveRoot, entry, "bin", baseName));
3038
+ candidates.push(path6.join(driveRoot, entry, "bin", `${baseName}.bat`));
3039
+ candidates.push(path6.join(driveRoot, entry, "bin", baseName));
2868
3040
  }
2869
3041
  }
2870
3042
  return candidates;
@@ -2884,6 +3056,7 @@ function createInteractiveServer(spec) {
2884
3056
  rootMarkers: spec.root.rootMarkers,
2885
3057
  fallbackFor: spec.fallbackFor,
2886
3058
  requiresProjectRoot: spec.requiresProjectRoot,
3059
+ executesProjectCode: spec.executesProjectCode,
2887
3060
  availabilityKey: typeof spec.command === "string" && isSimpleCommand(spec.command) ? spec.command : void 0,
2888
3061
  async spawn(root) {
2889
3062
  const command = typeof spec.command === "function" ? spec.command(root) : spec.command;
@@ -2920,7 +3093,7 @@ function PriorityRoot(markerGroups, excludePatterns, stopDir) {
2920
3093
  }, markerGroups.flat());
2921
3094
  }
2922
3095
  var FileDirRoot = async (file) => {
2923
- const candidate = path7.resolve(path7.dirname(file));
3096
+ const candidate = path6.resolve(path6.dirname(file));
2924
3097
  return nearestNonExcludedFallbackRoot(candidate);
2925
3098
  };
2926
3099
  function RootWithFallback(primary, fallback = FileDirRoot) {
@@ -2942,16 +3115,16 @@ function markerProbeDir(dir, pattern) {
2942
3115
  const normalized = toPosix(pattern);
2943
3116
  const slash = normalized.lastIndexOf("/");
2944
3117
  const parentPattern = slash >= 0 ? normalized.slice(0, slash) : "";
2945
- return parentPattern ? path7.join(dir, ...parentPattern.split("/").filter(Boolean)) : dir;
3118
+ return parentPattern ? path6.join(dir, ...parentPattern.split("/").filter(Boolean)) : dir;
2946
3119
  }
2947
3120
  async function markerExists(dir, pattern) {
2948
3121
  if (!pattern.includes("*")) {
2949
3122
  try {
2950
- await stat(path7.join(dir, pattern));
3123
+ await stat(path6.join(dir, pattern));
2951
3124
  return true;
2952
3125
  } catch (err) {
2953
3126
  if (isPermissionFsError(err)) {
2954
- logSessionStart(`lsp root marker skipped: permission error stat ${path7.join(dir, pattern)}`);
3127
+ logSessionStart(`lsp root marker skipped: permission error stat ${path6.join(dir, pattern)}`);
2955
3128
  }
2956
3129
  return false;
2957
3130
  }
@@ -2987,7 +3160,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
2987
3160
  subdirPatterns.push(pattern);
2988
3161
  }
2989
3162
  return withRootMarkers(async (file) => {
2990
- const startDir = path7.resolve(path7.dirname(file));
3163
+ const startDir = path6.resolve(path6.dirname(file));
2991
3164
  const dirKey = normalizeMapKey(startDir);
2992
3165
  const cached = cache.get(dirKey);
2993
3166
  if (cached !== void 0 && Date.now() - cached.walkedAt < FRESHNESS_CADENCE_MS && await bounded(dirMtimesStillFreshAsync(cached.probedDirs), rootMtimeBound("lsp-root-memo-freshness")) === true)
@@ -2999,10 +3172,10 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
2999
3172
  const walkedAt = Date.now();
3000
3173
  const promise = (async () => {
3001
3174
  let currentDir = startDir;
3002
- const fsRoot = path7.parse(currentDir).root;
3003
- const stop = stopDir ? path7.resolve(stopDir) : fsRoot;
3175
+ const fsRoot = path6.parse(currentDir).root;
3176
+ const stop = stopDir ? path6.resolve(stopDir) : fsRoot;
3004
3177
  while (true) {
3005
- if (stop !== fsRoot && currentDir.startsWith(stop + path7.sep) === false && currentDir !== stop) {
3178
+ if (stop !== fsRoot && currentDir.startsWith(stop + path6.sep) === false && currentDir !== stop) {
3006
3179
  break;
3007
3180
  }
3008
3181
  const stepDirs = [
@@ -3020,7 +3193,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
3020
3193
  }
3021
3194
  }
3022
3195
  if (excluded) {
3023
- currentDir = path7.dirname(currentDir);
3196
+ currentDir = path6.dirname(currentDir);
3024
3197
  continue;
3025
3198
  }
3026
3199
  }
@@ -3032,7 +3205,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
3032
3205
  if (currentDir === stop || currentDir === fsRoot) {
3033
3206
  break;
3034
3207
  }
3035
- currentDir = path7.dirname(currentDir);
3208
+ currentDir = path6.dirname(currentDir);
3036
3209
  }
3037
3210
  return void 0;
3038
3211
  })();
@@ -3074,17 +3247,17 @@ async function findAncestorFile(startDir, ...relativeSegments) {
3074
3247
  }
3075
3248
  async function findAncestorFileAmong(startDir, candidateSegmentLists) {
3076
3249
  const fs5 = await import("node:fs/promises");
3077
- let currentDir = path7.resolve(startDir);
3250
+ let currentDir = path6.resolve(startDir);
3078
3251
  while (!isAtOrAboveHomeDir(currentDir)) {
3079
3252
  for (const segments of candidateSegmentLists) {
3080
- const candidate = path7.join(currentDir, ...segments);
3253
+ const candidate = path6.join(currentDir, ...segments);
3081
3254
  try {
3082
3255
  await fs5.access(candidate);
3083
3256
  return candidate;
3084
3257
  } catch {
3085
3258
  }
3086
3259
  }
3087
- const parent = path7.dirname(currentDir);
3260
+ const parent = path6.dirname(currentDir);
3088
3261
  if (parent === currentDir)
3089
3262
  break;
3090
3263
  currentDir = parent;
@@ -3100,19 +3273,19 @@ function resetClassicTsRepairGuard() {
3100
3273
  classicTsRepairState().attempted = false;
3101
3274
  }
3102
3275
  function typescriptDirsForTsc(tscPath) {
3103
- const binDir = path7.dirname(tscPath);
3276
+ const binDir = path6.dirname(tscPath);
3104
3277
  return [
3105
- path7.join(binDir, "..", "typescript"),
3106
- path7.join(binDir, "..", "..", "typescript")
3278
+ path6.join(binDir, "..", "typescript"),
3279
+ path6.join(binDir, "..", "..", "typescript")
3107
3280
  ];
3108
3281
  }
3109
3282
  async function typescriptVersionForTsc(tscPath) {
3110
- if (!path7.isAbsolute(tscPath))
3283
+ if (!path6.isAbsolute(tscPath))
3111
3284
  return void 0;
3112
3285
  for (const dir of typescriptDirsForTsc(tscPath)) {
3113
3286
  let manifest;
3114
3287
  try {
3115
- manifest = await readFile(path7.join(dir, "package.json"), "utf8");
3288
+ manifest = await readFile(path6.join(dir, "package.json"), "utf8");
3116
3289
  } catch {
3117
3290
  continue;
3118
3291
  }
@@ -3134,25 +3307,45 @@ async function typescriptVersionForTsc(tscPath) {
3134
3307
  }
3135
3308
  return void 0;
3136
3309
  }
3137
- async function findTsserverPath(root, allowInstall) {
3310
+ async function findTsserverPath(root, allowInstall, options) {
3138
3311
  const fs5 = await import("node:fs/promises");
3312
+ const projectRoots = await Promise.all([root, options?.sessionRoot ?? process.cwd(), process.cwd()].map((dir) => fs5.realpath(dir).catch(() => path6.resolve(dir))));
3313
+ const admitCandidate = async (candidate, projectSupplied) => {
3314
+ try {
3315
+ const real = await fs5.realpath(candidate);
3316
+ if (path6.basename(real) !== "tsserver.js" || !(await fs5.stat(real)).isFile())
3317
+ return void 0;
3318
+ const manifest = JSON.parse(await fs5.readFile(path6.join(path6.dirname(real), "..", "package.json"), "utf8"));
3319
+ if (typeof manifest?.version !== "string" || !manifest.version)
3320
+ return void 0;
3321
+ return admitProjectSuppliedTsserver(real, options?.sessionRoot ?? process.cwd(), projectSupplied || projectRoots.some((dir) => isUnderDir(real, dir)), options?.projectCodeAllowed);
3322
+ } catch {
3323
+ return void 0;
3324
+ }
3325
+ };
3139
3326
  const ancestorHit = await findAncestorFile(root, "node_modules", "typescript", "lib", "tsserver.js");
3140
- if (ancestorHit)
3141
- return ancestorHit;
3142
- const cwdCandidate = path7.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
3327
+ if (ancestorHit) {
3328
+ const admittedAncestor = await admitCandidate(ancestorHit, true);
3329
+ if (admittedAncestor)
3330
+ return admittedAncestor;
3331
+ }
3332
+ const cwdCandidate = path6.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
3143
3333
  try {
3144
3334
  await fs5.access(cwdCandidate);
3145
- return cwdCandidate;
3335
+ const admittedCwd = await admitCandidate(cwdCandidate, false);
3336
+ if (admittedCwd)
3337
+ return admittedCwd;
3146
3338
  } catch {
3147
3339
  }
3148
3340
  const tsserverForTsc = async (tscPath) => {
3149
- if (!tscPath)
3341
+ if (!tscPath || !path6.isAbsolute(tscPath))
3150
3342
  return void 0;
3151
3343
  for (const dir of typescriptDirsForTsc(tscPath)) {
3152
- const candidate = path7.join(dir, "lib", "tsserver.js");
3344
+ const candidate = path6.join(dir, "lib", "tsserver.js");
3153
3345
  try {
3154
- await fs5.access(candidate);
3155
- return candidate;
3346
+ const admitted = await admitCandidate(candidate, false);
3347
+ if (admitted)
3348
+ return admitted;
3156
3349
  } catch {
3157
3350
  }
3158
3351
  }
@@ -3178,10 +3371,10 @@ async function findTsserverPath(root, allowInstall) {
3178
3371
  return tsserverForTsc(repairedTsc);
3179
3372
  }
3180
3373
  async function findNativeTypeScriptLsp(root) {
3181
- let currentDir = path7.resolve(root);
3374
+ let currentDir = path6.resolve(root);
3182
3375
  while (!isAtOrAboveHomeDir(currentDir)) {
3183
- const typescriptDir = path7.join(currentDir, "node_modules", "typescript");
3184
- const packageJsonPath = path7.join(typescriptDir, "package.json");
3376
+ const typescriptDir = path6.join(currentDir, "node_modules", "typescript");
3377
+ const packageJsonPath = path6.join(typescriptDir, "package.json");
3185
3378
  let packageJsonText;
3186
3379
  try {
3187
3380
  packageJsonText = await readFile(packageJsonPath, "utf8");
@@ -3195,7 +3388,7 @@ async function findNativeTypeScriptLsp(root) {
3195
3388
  return void 0;
3196
3389
  } catch {
3197
3390
  }
3198
- const parent = path7.dirname(currentDir);
3391
+ const parent = path6.dirname(currentDir);
3199
3392
  if (parent === currentDir)
3200
3393
  return void 0;
3201
3394
  currentDir = parent;
@@ -3215,7 +3408,7 @@ async function findNativeTypeScriptLsp(root) {
3215
3408
  const major = /^\d+$/.test(majorText) ? Number(majorText) : Number.NaN;
3216
3409
  if (!Number.isFinite(major) || major < 7)
3217
3410
  return void 0;
3218
- const localTsc = path7.join(currentDir, "node_modules", ".bin", "tsc");
3411
+ const localTsc = path6.join(currentDir, "node_modules", ".bin", "tsc");
3219
3412
  const candidates = process.platform === "win32" ? [`${localTsc}.cmd`, `${localTsc}.exe`, localTsc] : [localTsc];
3220
3413
  for (const command of candidates) {
3221
3414
  try {
@@ -3231,23 +3424,23 @@ async function findNativeTypeScriptLsp(root) {
3231
3424
  function dotnetToolCandidates(tool) {
3232
3425
  const home = os6.homedir();
3233
3426
  return [
3234
- path7.join(PI_LENS_BIN_DIR2, `${tool}.exe`),
3235
- path7.join(PI_LENS_BIN_DIR2, tool),
3236
- path7.join(home, ".dotnet", "tools", `${tool}.exe`),
3237
- path7.join(home, ".dotnet", "tools", tool),
3427
+ path6.join(PI_LENS_BIN_DIR2, `${tool}.exe`),
3428
+ path6.join(PI_LENS_BIN_DIR2, tool),
3429
+ path6.join(home, ".dotnet", "tools", `${tool}.exe`),
3430
+ path6.join(home, ".dotnet", "tools", tool),
3238
3431
  tool
3239
3432
  ].filter(Boolean);
3240
3433
  }
3241
3434
  function binExeVariants(dir, tool) {
3242
- return process.platform === "win32" ? [path7.join(dir, `${tool}.exe`), path7.join(dir, tool)] : [path7.join(dir, tool)];
3435
+ return process.platform === "win32" ? [path6.join(dir, `${tool}.exe`), path6.join(dir, tool)] : [path6.join(dir, tool)];
3243
3436
  }
3244
3437
  function goBinCandidates(tool) {
3245
- const gopath = process.env.GOPATH?.split(path7.delimiter)[0] || path7.join(os6.homedir(), "go");
3246
- return [tool, ...binExeVariants(path7.join(gopath, "bin"), tool)];
3438
+ const gopath = process.env.GOPATH?.split(path6.delimiter)[0] || path6.join(os6.homedir(), "go");
3439
+ return [tool, ...binExeVariants(path6.join(gopath, "bin"), tool)];
3247
3440
  }
3248
3441
  function cargoBinCandidates(tool) {
3249
- const cargoHome = process.env.CARGO_HOME || path7.join(os6.homedir(), ".cargo");
3250
- return [tool, ...binExeVariants(path7.join(cargoHome, "bin"), tool)];
3442
+ const cargoHome = process.env.CARGO_HOME || path6.join(os6.homedir(), ".cargo");
3443
+ return [tool, ...binExeVariants(path6.join(cargoHome, "bin"), tool)];
3251
3444
  }
3252
3445
  async function tryGemInstall(gem) {
3253
3446
  const { join: join3 } = await import("node:path");
@@ -3285,7 +3478,7 @@ var TS_TOOLING_MARKERS = [
3285
3478
  ];
3286
3479
  var TS_FAMILY_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
3287
3480
  function isTsFamilyFile(file) {
3288
- return TS_FAMILY_EXTENSIONS.has(path7.extname(file).toLowerCase());
3481
+ return TS_FAMILY_EXTENSIONS.has(path6.extname(file).toLowerCase());
3289
3482
  }
3290
3483
  function tsConfigMarkersForFile(file) {
3291
3484
  return isTsFamilyFile(file) ? ["tsconfig.json"] : TS_CONFIG_MARKERS;
@@ -3306,40 +3499,40 @@ async function findTypeScriptProjectRoot(file) {
3306
3499
  return isSameOrWithin(toolingRoot, configRoot) ? configRoot : toolingRoot;
3307
3500
  }
3308
3501
  async function findExtensionBoundedRoot(file, extensionRootKey) {
3309
- const startDir = path7.resolve(path7.dirname(file));
3502
+ const startDir = path6.resolve(path6.dirname(file));
3310
3503
  let currentDir = startDir;
3311
3504
  const configMarkers = tsConfigMarkersForFile(file);
3312
3505
  while (true) {
3313
3506
  for (const pattern of configMarkers) {
3314
3507
  try {
3315
- await stat(path7.join(currentDir, pattern));
3508
+ await stat(path6.join(currentDir, pattern));
3316
3509
  return currentDir;
3317
3510
  } catch {
3318
3511
  }
3319
3512
  }
3320
3513
  for (const pattern of TS_TOOLING_MARKERS) {
3321
3514
  try {
3322
- await stat(path7.join(currentDir, pattern));
3515
+ await stat(path6.join(currentDir, pattern));
3323
3516
  return currentDir;
3324
3517
  } catch {
3325
3518
  }
3326
3519
  }
3327
- const currentKey = normalizeEphemeralMapKey(path7.resolve(currentDir));
3520
+ const currentKey = normalizeEphemeralMapKey(path6.resolve(currentDir));
3328
3521
  if (currentKey === extensionRootKey)
3329
3522
  return void 0;
3330
- const parent = path7.dirname(currentDir);
3523
+ const parent = path6.dirname(currentDir);
3331
3524
  if (parent === currentDir)
3332
3525
  return void 0;
3333
3526
  currentDir = parent;
3334
3527
  }
3335
3528
  }
3336
3529
  async function hasAgentLevelProjectMarker(extensionRootKey) {
3337
- const agentDir = path7.dirname(extensionRootKey);
3530
+ const agentDir = path6.dirname(extensionRootKey);
3338
3531
  if (!agentDir || agentDir === extensionRootKey)
3339
3532
  return false;
3340
3533
  for (const pattern of [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]) {
3341
3534
  try {
3342
- await stat(path7.join(agentDir, pattern));
3535
+ await stat(path6.join(agentDir, pattern));
3343
3536
  return true;
3344
3537
  } catch {
3345
3538
  }
@@ -3367,14 +3560,14 @@ var TypeScriptServer = {
3367
3560
  idleEviction: "transparent",
3368
3561
  role: "language",
3369
3562
  name: "TypeScript Language Server",
3563
+ projectLocalCommand: "typescript-language-server",
3370
3564
  extensions: JS_TS_LSP_EXTENSIONS,
3371
3565
  autoPropagateDiagnostics: true,
3372
3566
  root: TypeScriptRoot,
3373
3567
  rootMarkers: TypeScriptRoot.rootMarkers,
3374
3568
  async spawn(root, options) {
3375
- const fs5 = await import("node:fs/promises");
3376
3569
  const nativeLsp = await findNativeTypeScriptLsp(root);
3377
- if (nativeLsp) {
3570
+ if (nativeLsp && admitProjectSuppliedTsserver(nativeLsp.command, root, true, options?.projectCodeAllowed)) {
3378
3571
  const env2 = await getToolEnvironment();
3379
3572
  logSessionStart(`lsp typescript-native: version=${nativeLsp.version} command=${nativeLsp.command}`);
3380
3573
  const proc2 = await launchLSP(nativeLsp.command, ["--lsp", "--stdio"], {
@@ -3398,14 +3591,10 @@ var TypeScriptServer = {
3398
3591
  return void 0;
3399
3592
  }
3400
3593
  }
3401
- let tsserverPath = await findTsserverPath(root, options?.allowInstall);
3594
+ const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
3402
3595
  if (!tsserverPath) {
3403
- const localCandidate = path7.join(path7.dirname(lspPath), "..", "typescript", "lib", "tsserver.js");
3404
- try {
3405
- await fs5.access(localCandidate);
3406
- tsserverPath = localCandidate;
3407
- } catch {
3408
- }
3596
+ admitProjectSuppliedTsserver(void 0, root, true, options?.projectCodeAllowed);
3597
+ return void 0;
3409
3598
  }
3410
3599
  if (tsserverPath)
3411
3600
  source = "managed";
@@ -3521,13 +3710,13 @@ var PythonServer = {
3521
3710
  if (!pyrightPath)
3522
3711
  return void 0;
3523
3712
  source = "managed";
3524
- const binDir = path7.dirname(pyrightPath);
3713
+ const binDir = path6.dirname(pyrightPath);
3525
3714
  const isWindows2 = process.platform === "win32";
3526
3715
  const managedCandidates = isWindows2 ? [
3527
- path7.join(binDir, "pyright-langserver.cmd"),
3528
- path7.join(binDir, "pyright-langserver"),
3716
+ path6.join(binDir, "pyright-langserver.cmd"),
3717
+ path6.join(binDir, "pyright-langserver"),
3529
3718
  "pyright-langserver"
3530
- ] : [path7.join(binDir, "pyright-langserver"), "pyright-langserver"];
3719
+ ] : [path6.join(binDir, "pyright-langserver"), "pyright-langserver"];
3531
3720
  const resolved = await resolveAndLaunch({ candidates: managedCandidates, args: ["--stdio"], cwd: root, env }, false);
3532
3721
  if (!resolved)
3533
3722
  return void 0;
@@ -3596,7 +3785,7 @@ var GoServer = {
3596
3785
  }
3597
3786
  };
3598
3787
  function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
3599
- const relativePath = path7.relative(parentDir, childDir).split(path7.sep).join("/");
3788
+ const relativePath = path6.relative(parentDir, childDir).split(path6.sep).join("/");
3600
3789
  if (relativePath === "" || relativePath.startsWith(".."))
3601
3790
  return false;
3602
3791
  const matches = (pattern) => matchesWorkspaceMemberPattern(pattern, relativePath, CARGO_WORKSPACE_MEMBER_DIALECT, () => recordDegradationOnce({
@@ -3610,7 +3799,7 @@ function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
3610
3799
  return readCargoWorkspaceMembers(workspaceContent).some(matches);
3611
3800
  }
3612
3801
  function sessionHoistCeiling(sessionCwd, file) {
3613
- return isSameOrWithin(path7.resolve(sessionCwd), path7.resolve(file)) ? path7.resolve(sessionCwd) : void 0;
3802
+ return isSameOrWithin(path6.resolve(sessionCwd), path6.resolve(file)) ? path6.resolve(sessionCwd) : void 0;
3614
3803
  }
3615
3804
  function RustWorkspaceRoot() {
3616
3805
  const crateRoot = createRootDetector(["Cargo.toml", "Cargo.lock"]);
@@ -3621,14 +3810,14 @@ function RustWorkspaceRoot() {
3621
3810
  const sessionCwd = process.cwd();
3622
3811
  const stop = sessionHoistCeiling(sessionCwd, file);
3623
3812
  let current = root;
3624
- const fsRoot = path7.parse(current).root;
3813
+ const fsRoot = path6.parse(current).root;
3625
3814
  while (true) {
3626
3815
  if (stop !== void 0 && current === stop)
3627
3816
  break;
3628
- const parent = path7.dirname(current);
3817
+ const parent = path6.dirname(current);
3629
3818
  if (parent === current || parent === fsRoot)
3630
3819
  break;
3631
- const parentCargoPath = path7.join(parent, "Cargo.toml");
3820
+ const parentCargoPath = path6.join(parent, "Cargo.toml");
3632
3821
  const parentCargoContent = await readTextFileOrUndefined(parentCargoPath);
3633
3822
  if (parentCargoContent !== void 0 && hasCargoWorkspaceTable(parentCargoContent)) {
3634
3823
  if (cargoWorkspaceDeclaresMember(parentCargoContent, parent, root)) {
@@ -3656,9 +3845,9 @@ async function declaresMavenModule(parentDir, parentPomPath, childDir) {
3656
3845
  const modulesBlock = content.match(/<modules>([\s\S]*?)<\/modules>/);
3657
3846
  if (!modulesBlock)
3658
3847
  return false;
3659
- const resolvedChild = path7.resolve(childDir);
3848
+ const resolvedChild = path6.resolve(childDir);
3660
3849
  for (const match of modulesBlock[1].matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
3661
- if (pathsEqual(path7.resolve(parentDir, match[1]), resolvedChild))
3850
+ if (pathsEqual(path6.resolve(parentDir, match[1]), resolvedChild))
3662
3851
  return true;
3663
3852
  }
3664
3853
  return false;
@@ -3682,15 +3871,15 @@ function JavaWorkspaceRoot() {
3682
3871
  const stop = sessionHoistCeiling(sessionCwd, file);
3683
3872
  let current = root;
3684
3873
  let lastHop = root;
3685
- const fsRoot = path7.parse(current).root;
3874
+ const fsRoot = path6.parse(current).root;
3686
3875
  while (true) {
3687
3876
  if (stop !== void 0 && current === stop)
3688
3877
  break;
3689
- const parent = path7.dirname(current);
3878
+ const parent = path6.dirname(current);
3690
3879
  if (parent === current || parent === fsRoot)
3691
3880
  break;
3692
3881
  if (await markerExists(parent, "pom.xml")) {
3693
- const parentPom = path7.join(parent, "pom.xml");
3882
+ const parentPom = path6.join(parent, "pom.xml");
3694
3883
  if (!await declaresMavenModule(parent, parentPom, lastHop))
3695
3884
  break;
3696
3885
  current = parent;
@@ -3709,6 +3898,7 @@ var RustServer = {
3709
3898
  // Measured (#3750): rust-analyzer answers an empty result for a detached file.
3710
3899
  requiresProjectRoot: true,
3711
3900
  name: "rust-analyzer",
3901
+ executesProjectCode: true,
3712
3902
  extensions: KIND_EXTENSIONS["rust"],
3713
3903
  // No FileDirRoot fallback (#201): rust-analyzer is a heavy workspace server
3714
3904
  // that is useless without a Cargo manifest. With the fallback, every .rs file
@@ -3742,6 +3932,7 @@ var RubyServer = {
3742
3932
  idleEviction: "unmeasured",
3743
3933
  role: "language",
3744
3934
  name: "Ruby LSP",
3935
+ executesProjectCode: true,
3745
3936
  extensions: KIND_EXTENSIONS["ruby"],
3746
3937
  root: RootWithFallback(PriorityRoot([["Gemfile", ".ruby-version"], [".git"]])),
3747
3938
  // Ruby LSP may need extra time to finish composed-bundle setup before it can
@@ -3794,17 +3985,17 @@ var PHPServer = {
3794
3985
  return {
3795
3986
  ...result,
3796
3987
  initialization: {
3797
- storagePath: path7.join(getGlobalPiLensDir(), "intelephense")
3988
+ storagePath: path6.join(getGlobalPiLensDir(), "intelephense")
3798
3989
  }
3799
3990
  };
3800
3991
  }
3801
3992
  };
3802
3993
  function buildPsesArgs(bundleDir) {
3803
- const script = path7.join(bundleDir, "PowerShellEditorServices", "Start-EditorServices.ps1");
3804
- const sessionDir = path7.join(getGlobalPiLensDir(), "pses", `${process.pid}-${Date.now()}`);
3994
+ const script = path6.join(bundleDir, "PowerShellEditorServices", "Start-EditorServices.ps1");
3995
+ const sessionDir = path6.join(getGlobalPiLensDir(), "pses", `${process.pid}-${Date.now()}`);
3805
3996
  mkdirSync2(sessionDir, { recursive: true });
3806
- const logPath = path7.join(sessionDir, "pses.log");
3807
- const sessionDetailsPath = path7.join(sessionDir, "session.json");
3997
+ const logPath = path6.join(sessionDir, "pses.log");
3998
+ const sessionDetailsPath = path6.join(sessionDir, "session.json");
3808
3999
  return [
3809
4000
  "-NoLogo",
3810
4001
  "-NoProfile",
@@ -3838,6 +4029,7 @@ var PowerShellServer = {
3838
4029
  idleEviction: "unmeasured",
3839
4030
  role: "language",
3840
4031
  name: "PowerShell Editor Services",
4032
+ executesProjectCode: true,
3841
4033
  extensions: KIND_EXTENSIONS["powershell"],
3842
4034
  // Index at the workspace (script modules reference siblings); fall back to the
3843
4035
  // file dir.
@@ -3858,6 +4050,7 @@ var CSharpServer = {
3858
4050
  // Documented (#3750): csharp-ls needs a solution or project.
3859
4051
  requiresProjectRoot: true,
3860
4052
  name: "csharp-ls",
4053
+ executesProjectCode: true,
3861
4054
  extensions: KIND_EXTENSIONS["csharp"],
3862
4055
  // No FileDirRoot fallback (#201): csharp-ls is a workspace server and should
3863
4056
  // not spawn once per source directory before a .sln/.csproj exists. Glob root
@@ -3881,6 +4074,7 @@ var CSharpServer = {
3881
4074
  var OmniSharpServer = createInteractiveServer({
3882
4075
  id: "omnisharp",
3883
4076
  name: "OmniSharp",
4077
+ executesProjectCode: true,
3884
4078
  // Documented (#3750): OmniSharp needs a solution or project.
3885
4079
  requiresProjectRoot: true,
3886
4080
  fallbackFor: "csharp",
@@ -3897,6 +4091,7 @@ var FSharpServer = {
3897
4091
  // Documented (#3750): FSAutocomplete needs a project.
3898
4092
  requiresProjectRoot: true,
3899
4093
  name: "FSAutocomplete",
4094
+ executesProjectCode: true,
3900
4095
  extensions: KIND_EXTENSIONS["fsharp"],
3901
4096
  root: createRootDetector([...DOTNET_FSHARP_ROOT_MARKERS]),
3902
4097
  async spawn(root, options) {
@@ -3916,6 +4111,7 @@ var FSharpServer = {
3916
4111
  var JavaServer = createInteractiveServer({
3917
4112
  id: "java",
3918
4113
  name: "JDT Language Server",
4114
+ executesProjectCode: true,
3919
4115
  extensions: KIND_EXTENSIONS["java"],
3920
4116
  root: RootWithFallback(JavaWorkspaceRoot()),
3921
4117
  language: "java",
@@ -3928,6 +4124,7 @@ var KotlinServer = {
3928
4124
  idleEviction: "unmeasured",
3929
4125
  role: "language",
3930
4126
  name: "Kotlin Language Server",
4127
+ executesProjectCode: true,
3931
4128
  extensions: KIND_EXTENSIONS["kotlin"],
3932
4129
  root: RootWithFallback(createRootDetector(["build.gradle.kts", "build.gradle", "pom.xml"])),
3933
4130
  async spawn(root, options) {
@@ -3943,9 +4140,26 @@ var KotlinServer = {
3943
4140
  }, options?.allowInstall);
3944
4141
  }
3945
4142
  };
4143
+ var LeanServer = createInteractiveServer({
4144
+ id: "lean",
4145
+ name: "Lean 4 Language Server",
4146
+ extensions: KIND_EXTENSIONS.lean,
4147
+ root: RootWithFallback(createRootDetector([...LEAN_ROOT_MARKERS])),
4148
+ language: "lean",
4149
+ // Documented (#3750): `lake serve` analyses a file only when a Lake project
4150
+ // roots it; a root-fallback empty answer is unconfirmed, not clean.
4151
+ requiresProjectRoot: true,
4152
+ // `lake serve` loads and interprets the project's `lakefile.lean` and its
4153
+ // imported build scripts, so it executes project-owned code: refuse it until
4154
+ // the host grants project trust (#4269).
4155
+ executesProjectCode: true,
4156
+ command: "lake",
4157
+ args: ["serve"]
4158
+ });
3946
4159
  var SwiftServer = createInteractiveServer({
3947
4160
  id: "swift",
3948
4161
  name: "SourceKit-LSP",
4162
+ executesProjectCode: true,
3949
4163
  extensions: KIND_EXTENSIONS["swift"],
3950
4164
  root: createRootDetector(["Package.swift"]),
3951
4165
  language: "swift",
@@ -3953,6 +4167,7 @@ var SwiftServer = createInteractiveServer({
3953
4167
  });
3954
4168
  var DartServer = createInteractiveServer({
3955
4169
  id: "dart",
4170
+ executesProjectCode: true,
3956
4171
  name: "Dart Analysis Server",
3957
4172
  extensions: KIND_EXTENSIONS["dart"],
3958
4173
  root: RootWithFallback(createRootDetector(["pubspec.yaml"])),
@@ -4006,6 +4221,7 @@ var CppServer = createTreeBinaryServer({
4006
4221
  });
4007
4222
  var ZigServer = {
4008
4223
  id: "zig",
4224
+ executesProjectCode: true,
4009
4225
  idleEviction: "unmeasured",
4010
4226
  role: "language",
4011
4227
  name: "ZLS",
@@ -4023,6 +4239,7 @@ var ZigServer = {
4023
4239
  var HaskellServer = createInteractiveServer({
4024
4240
  id: "haskell",
4025
4241
  name: "Haskell Language Server",
4242
+ executesProjectCode: true,
4026
4243
  extensions: KIND_EXTENSIONS["haskell"],
4027
4244
  root: createRootDetector(["stack.yaml", "cabal.project", "*.cabal"]),
4028
4245
  language: "haskell",
@@ -4032,6 +4249,7 @@ var HaskellServer = createInteractiveServer({
4032
4249
  var ElixirServer = createInteractiveServer({
4033
4250
  id: "elixir",
4034
4251
  name: "ElixirLS",
4252
+ executesProjectCode: true,
4035
4253
  extensions: KIND_EXTENSIONS["elixir"],
4036
4254
  root: RootWithFallback(createRootDetector(["mix.exs"])),
4037
4255
  language: "elixir",
@@ -4042,6 +4260,7 @@ var ElixirExpertServer = {
4042
4260
  idleEviction: "unmeasured",
4043
4261
  role: "language",
4044
4262
  name: "Expert",
4263
+ executesProjectCode: true,
4045
4264
  fallbackFor: "elixir",
4046
4265
  extensions: KIND_EXTENSIONS["elixir"],
4047
4266
  root: RootWithFallback(createRootDetector(["mix.exs"])),
@@ -4074,6 +4293,7 @@ var GleamServer = {
4074
4293
  };
4075
4294
  var TinymistServer = {
4076
4295
  id: "tinymist",
4296
+ executesProjectCode: true,
4077
4297
  idleEviction: "unmeasured",
4078
4298
  role: "language",
4079
4299
  name: "Tinymist",
@@ -4110,6 +4330,7 @@ var MarksmanServer = {
4110
4330
  };
4111
4331
  var OCamlServer = createInteractiveServer({
4112
4332
  id: "ocaml",
4333
+ executesProjectCode: true,
4113
4334
  name: "ocamllsp",
4114
4335
  extensions: KIND_EXTENSIONS["ocaml"],
4115
4336
  root: createRootDetector(["dune-project", "opam"]),
@@ -4118,6 +4339,7 @@ var OCamlServer = createInteractiveServer({
4118
4339
  });
4119
4340
  var ClojureServer = {
4120
4341
  id: "clojure",
4342
+ executesProjectCode: true,
4121
4343
  idleEviction: "transparent",
4122
4344
  role: "language",
4123
4345
  name: "Clojure LSP",
@@ -4150,6 +4372,7 @@ var CueServer = {
4150
4372
  };
4151
4373
  var TerraformServer = {
4152
4374
  id: "terraform",
4375
+ executesProjectCode: true,
4153
4376
  idleEviction: "unmeasured",
4154
4377
  role: "language",
4155
4378
  name: "Terraform LSP",
@@ -4166,6 +4389,7 @@ var TerraformServer = {
4166
4389
  };
4167
4390
  var NixServer = createInteractiveServer({
4168
4391
  id: "nix",
4392
+ executesProjectCode: true,
4169
4393
  name: "nixd",
4170
4394
  extensions: KIND_EXTENSIONS["nix"],
4171
4395
  root: createRootDetector(["flake.nix"]),
@@ -4234,6 +4458,7 @@ var FishServer = {
4234
4458
  };
4235
4459
  var CMakeServer = {
4236
4460
  id: "cmake",
4461
+ executesProjectCode: true,
4237
4462
  idleEviction: "unmeasured",
4238
4463
  role: "language",
4239
4464
  name: "CMake Language Server",
@@ -4404,6 +4629,7 @@ var PrismaServer = {
4404
4629
  };
4405
4630
  var VueServer = {
4406
4631
  id: "vue",
4632
+ executesProjectCode: true,
4407
4633
  idleEviction: "unmeasured",
4408
4634
  role: "language",
4409
4635
  name: "Vue Language Server",
@@ -4426,9 +4652,9 @@ var VueServer = {
4426
4652
  clientWaitTimeoutMs: 3e4,
4427
4653
  initializeTimeoutMs: 3e4,
4428
4654
  async spawn(root, options) {
4429
- const tsserverPath = await findTsserverPath(root, options?.allowInstall);
4430
- const hasPackageJson = existsSync3(path7.join(root, "package.json"));
4431
- const hasNodeModules = existsSync3(path7.join(root, "node_modules"));
4655
+ const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
4656
+ const hasPackageJson = existsSync3(path6.join(root, "package.json"));
4657
+ const hasNodeModules = existsSync3(path6.join(root, "node_modules"));
4432
4658
  if (hasPackageJson && !hasNodeModules) {
4433
4659
  logSessionStart(`lsp vue: node_modules missing in ${root} \u2014 Vue navigation may be limited. Run: npm install (or pnpm/yarn install) in this project.`);
4434
4660
  }
@@ -4443,12 +4669,13 @@ var VueServer = {
4443
4669
  return {
4444
4670
  process: proc.process,
4445
4671
  source: proc.source,
4446
- initialization: tsserverPath ? { typescript: { tsdk: path7.dirname(tsserverPath) } } : void 0
4672
+ initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
4447
4673
  };
4448
4674
  }
4449
4675
  };
4450
4676
  var SvelteServer = {
4451
4677
  id: "svelte",
4678
+ executesProjectCode: true,
4452
4679
  idleEviction: "unmeasured",
4453
4680
  role: "language",
4454
4681
  name: "Svelte Language Server",
@@ -4469,7 +4696,7 @@ var SvelteServer = {
4469
4696
  clientWaitTimeoutMs: 2e4,
4470
4697
  initializeTimeoutMs: 2e4,
4471
4698
  async spawn(root, options) {
4472
- const tsserverPath = await findTsserverPath(root, options?.allowInstall);
4699
+ const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
4473
4700
  const proc = await resolveAndLaunch({
4474
4701
  candidates: [
4475
4702
  ...nodeBinCandidates(root, "svelteserver"),
@@ -4484,7 +4711,7 @@ var SvelteServer = {
4484
4711
  return {
4485
4712
  process: proc.process,
4486
4713
  source: proc.source,
4487
- initialization: tsserverPath ? { typescript: { tsdk: path7.dirname(tsserverPath) } } : void 0
4714
+ initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
4488
4715
  };
4489
4716
  }
4490
4717
  };
@@ -4735,6 +4962,7 @@ var LSP_SERVERS = [
4735
4962
  FSharpServer,
4736
4963
  JavaServer,
4737
4964
  KotlinServer,
4965
+ LeanServer,
4738
4966
  SwiftServer,
4739
4967
  DartServer,
4740
4968
  LuaServer,
@@ -4777,6 +5005,54 @@ function getServerById(id) {
4777
5005
  return LSP_SERVERS.find((server) => server.id === id);
4778
5006
  }
4779
5007
 
5008
+ // dist/clients/lsp/session-roots.js
5009
+ import path7 from "node:path";
5010
+ var SESSION_ROOT_CAP = 128;
5011
+ var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
5012
+ function noteEvictedRoots(evicted) {
5013
+ const roots = evicted.map(([root]) => root);
5014
+ if (roots.length > 0) {
5015
+ incrementDegradationCount({
5016
+ kind: "lsp-session-root-evicted",
5017
+ subject: `cap=${SESSION_ROOT_CAP}`,
5018
+ reason: `session root registry at capacity; will load the dropped root again on the next session start or tool call naming it (dropped: ${roots[0]})`
5019
+ });
5020
+ }
5021
+ return roots;
5022
+ }
5023
+ function registerSessionRoot(cwd) {
5024
+ const root = path7.resolve(cwd);
5025
+ if (sessionRoots.has(root))
5026
+ return [];
5027
+ return noteEvictedRoots(sessionRoots.set(root, void 0));
5028
+ }
5029
+ function setSessionRootConfig(cwd, config) {
5030
+ return noteEvictedRoots(sessionRoots.set(path7.resolve(cwd), config));
5031
+ }
5032
+ function sessionRootConfigEntries() {
5033
+ return sessionRoots;
5034
+ }
5035
+ function isSessionRootRegistered(cwd) {
5036
+ return sessionRoots.has(path7.resolve(cwd));
5037
+ }
5038
+ function shouldInitializeSessionRoot(cwd, readyRoots) {
5039
+ const normalized = path7.resolve(cwd);
5040
+ return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
5041
+ }
5042
+ function isOutsideAllSessionRoots(filePath) {
5043
+ if (sessionRoots.size === 0)
5044
+ return false;
5045
+ const resolved = path7.resolve(filePath);
5046
+ for (const root of sessionRoots.keys()) {
5047
+ if (isSameOrWithin(root, resolved))
5048
+ return false;
5049
+ }
5050
+ return true;
5051
+ }
5052
+ function getSessionRootsForTelemetry(limit = 4) {
5053
+ return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
5054
+ }
5055
+
4780
5056
  export {
4781
5057
  findLocalTyposConfig,
4782
5058
  getAstGrepRuleSources,
@@ -4784,6 +5060,8 @@ export {
4784
5060
  isAuxiliary,
4785
5061
  serverTraits,
4786
5062
  registerRunnerId,
5063
+ withLspProjectCodePermission,
5064
+ refuseUntrustedLspExecution,
4787
5065
  BUILTIN_SERVER_RUNNER_COVERS,
4788
5066
  describeRootFallback,
4789
5067
  resolveLspServerCwd,