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
@@ -2,17 +2,17 @@ import { createRequire as __pilensCreateRequire } from "node:module"; const requ
2
2
  import {
3
3
  getLazyInstallAttempt,
4
4
  tryLazyInstall
5
- } from "./chunk-ZOEYVXSV.js";
5
+ } from "./chunk-OXXKQCSV.js";
6
6
  import {
7
7
  stripAnsi
8
8
  } from "./chunk-FC4RP4I2.js";
9
9
  import {
10
10
  isTrivyEnabled,
11
11
  resolveSeverityFloor
12
- } from "./chunk-YLN4K6WD.js";
12
+ } from "./chunk-66SXUJCA.js";
13
13
  import {
14
14
  rustClient
15
- } from "./chunk-3MRXIJ6I.js";
15
+ } from "./chunk-MRXKYPCS.js";
16
16
  import {
17
17
  findingsResult,
18
18
  finishParsedRun,
@@ -22,10 +22,10 @@ import {
22
22
  isRunnerSkipReason,
23
23
  parseToolRun,
24
24
  skipUnlessToolRan
25
- } from "./chunk-TA5L5KWQ.js";
25
+ } from "./chunk-2CD5RS6M.js";
26
26
  import {
27
27
  spawnFailedWithNoOutput
28
- } from "./chunk-FGALODG3.js";
28
+ } from "./chunk-UZ3TUTRV.js";
29
29
  import {
30
30
  coveringLaneAvailable,
31
31
  createAvailabilityChecker,
@@ -40,7 +40,7 @@ import {
40
40
  resolveToolCommand,
41
41
  resolveToolCommandWithInstallFallback,
42
42
  resolveVendorToolCommand
43
- } from "./chunk-NFXP47RV.js";
43
+ } from "./chunk-GOYRYZ2R.js";
44
44
  import {
45
45
  biomeConfigArgs,
46
46
  findCompiledClassesDir,
@@ -59,41 +59,39 @@ import {
59
59
  hasYamllintConfig,
60
60
  markdownlintConfigArgs,
61
61
  ruffConfigArgs
62
- } from "./chunk-MGIWSROG.js";
62
+ } from "./chunk-RPLINGVB.js";
63
63
  import {
64
64
  importFactProvider
65
- } from "./chunk-WSEWKCXU.js";
65
+ } from "./chunk-XCJN5IJU.js";
66
66
  import {
67
67
  functionFactProvider
68
- } from "./chunk-MQA2YBAH.js";
68
+ } from "./chunk-76MWC2K6.js";
69
69
  import {
70
70
  extractFactsFromTree
71
- } from "./chunk-TQFBZVCG.js";
71
+ } from "./chunk-GXW6K4YJ.js";
72
72
  import {
73
73
  computeImpactCascade
74
- } from "./chunk-WATC3IQR.js";
74
+ } from "./chunk-2B73ZPOK.js";
75
75
  import {
76
76
  goClient
77
- } from "./chunk-OYOB3ZFG.js";
78
- import {
79
- buildOrUpdateGraph,
80
- clearReviewGraphWorkspaceCache,
81
- fileContentProvider
82
- } from "./chunk-V5MEBST3.js";
77
+ } from "./chunk-XMSXXAHW.js";
83
78
  import {
84
79
  MAX_BLOCKING_RULE_COMPLEXITY,
85
80
  RUNTIME_CONFIG,
86
81
  applyDispositions,
87
82
  applyDispositionsMultiFile,
88
83
  buildEffectiveAstGrepCatalog,
84
+ buildOrUpdateGraph,
89
85
  calculateRuleComplexity,
90
86
  classifyDefect,
91
87
  classifyDiagnostic,
92
88
  classifyDiagnosticTier,
93
89
  clearPendingAuxiliaryCoverage,
90
+ clearReviewGraphWorkspaceCache,
94
91
  enabledAuxiliaryLspServerIds,
95
92
  exceedsLspSyncLimits,
96
93
  fetchTsserverProjectIdentity,
94
+ fileContentProvider,
97
95
  getLSPService,
98
96
  getRunnerTimeoutFloorMs,
99
97
  hasAnyDispositionMarks,
@@ -109,7 +107,7 @@ import {
109
107
  touchCoverageGap,
110
108
  tryWarmAttachedCodeActions,
111
109
  tryWarmAttachedDiagnostics
112
- } from "./chunk-MTDRLSI7.js";
110
+ } from "./chunk-PV6LR5P5.js";
113
111
  import {
114
112
  mapWithConcurrency
115
113
  } from "./chunk-XIMYZ3JA.js";
@@ -117,11 +115,16 @@ import {
117
115
  LSP_SERVERS,
118
116
  getAstGrepRuleSources,
119
117
  registerRunnerId
120
- } from "./chunk-IQZXOZ7S.js";
118
+ } from "./chunk-ESBQHFMJ.js";
121
119
  import {
122
120
  augmentPythonEnvironment,
123
121
  detectPythonEnvironment
124
- } from "./chunk-LNOMA3MP.js";
122
+ } from "./chunk-34WSVGEM.js";
123
+ import {
124
+ loadProjectSnapshot,
125
+ readJsonCache,
126
+ readJsonCacheAsync
127
+ } from "./chunk-ZXYDQ3TZ.js";
125
128
  import {
126
129
  BUNDLED_QUERIES_ROOT,
127
130
  classifyTreeSitterWasmError,
@@ -141,16 +144,11 @@ import {
141
144
  ruleFilesForLanguage,
142
145
  ruleSourceLanguages,
143
146
  walk
144
- } from "./chunk-UEAHAMEI.js";
147
+ } from "./chunk-QHJ6DQ2R.js";
145
148
  import {
146
149
  buildModuleGraph,
147
150
  clearModuleGraphCache
148
- } from "./chunk-6XX5HCLK.js";
149
- import {
150
- loadProjectSnapshot,
151
- readJsonCache,
152
- readJsonCacheAsync
153
- } from "./chunk-AXKPQ6ZI.js";
151
+ } from "./chunk-GBPP5P7X.js";
154
152
  import {
155
153
  WORD_INDEX_MAX_BYTES,
156
154
  deserializeWordIndex,
@@ -158,7 +156,7 @@ import {
158
156
  removeWordIndexDocumentAsync,
159
157
  scheduleWordIndexPersist,
160
158
  updateWordIndexDocumentForEdit
161
- } from "./chunk-7BX5DWSA.js";
159
+ } from "./chunk-SAEFPSB6.js";
162
160
  import {
163
161
  PathKeyedMap
164
162
  } from "./chunk-Z3CCVDUB.js";
@@ -166,26 +164,24 @@ import {
166
164
  WARM_CODE_ACTION_LOOKUP_LIMIT,
167
165
  contentHash,
168
166
  resolveRunnerPath
169
- } from "./chunk-XGUL4SLQ.js";
167
+ } from "./chunk-L3BLXZG7.js";
170
168
  import {
171
169
  isSpawnableCommand
172
- } from "./chunk-LD7WFTRX.js";
170
+ } from "./chunk-66VMUL7Q.js";
173
171
  import {
174
172
  logRunnerAdvisoryOnce,
175
173
  resolveRunnerCwd,
176
174
  resolveRunnerCwdWithReason
177
- } from "./chunk-IUR76K6A.js";
178
- import {
179
- findLocalBinUpwards
180
- } from "./chunk-T4QZ6FEH.js";
175
+ } from "./chunk-Q7DUK4LX.js";
181
176
  import {
182
- getProjectTrustState,
183
- projectTrustDenialReason
184
- } from "./chunk-D6YF5HKX.js";
177
+ findLocalBinUpwards,
178
+ localBinPath
179
+ } from "./chunk-AW7R2GWG.js";
185
180
  import {
186
181
  createAvailabilityProbeFlight,
182
+ getIsolatedNpxSpawnOptions,
187
183
  probeToolAsync
188
- } from "./chunk-CMU4RMJB.js";
184
+ } from "./chunk-RWWYJ623.js";
189
185
  import {
190
186
  classifyProbeFailure,
191
187
  createAvailabilityLatch,
@@ -195,13 +191,14 @@ import {
195
191
  logAvailabilityDecision,
196
192
  startHostStallSampler,
197
193
  transientRetryDelayMs
198
- } from "./chunk-O7HZX7CA.js";
194
+ } from "./chunk-VRZP76YM.js";
199
195
  import {
200
196
  getLspCapableKinds,
201
197
  getPrimaryDispatchGroup,
202
198
  resolveLanguageRootForFile
203
- } from "./chunk-VYKKMYVT.js";
199
+ } from "./chunk-QOBUHWHX.js";
204
200
  import {
201
+ getGlobalPiLensDir,
205
202
  getProjectDataDir,
206
203
  isInSpawnTimeoutCooldown,
207
204
  isTestFile,
@@ -209,19 +206,25 @@ import {
209
206
  noteSpawnTimeout,
210
207
  resolvePiLensFlag,
211
208
  safeSpawnAsync
212
- } from "./chunk-T54VJRAD.js";
209
+ } from "./chunk-C34ZXZ7O.js";
213
210
  import {
214
211
  detectFileKind
215
- } from "./chunk-64LU2OVH.js";
212
+ } from "./chunk-PHDMFAKM.js";
216
213
  import {
217
214
  classifyGeneratedOrArtifactDetailed,
218
215
  detectFileRole,
219
- loadPiLensProjectConfig
220
- } from "./chunk-N2IRDBZI.js";
216
+ loadPiLensProjectConfig,
217
+ resolvePiLensConfig
218
+ } from "./chunk-2BBLFX75.js";
221
219
  import {
222
220
  findNearestDirWithAnyBasename,
223
- findNearestDirWithMarker
224
- } from "./chunk-Z6BB4JLQ.js";
221
+ findNearestDirWithMarker,
222
+ getPiLensGlobalConfigPath
223
+ } from "./chunk-XVF2VVXP.js";
224
+ import {
225
+ getProjectTrustState,
226
+ projectTrustDenialReason
227
+ } from "./chunk-ZANLILYD.js";
225
228
  import {
226
229
  killedForOutputCap,
227
230
  truncatedByOutputCap,
@@ -230,26 +233,26 @@ import {
230
233
  import {
231
234
  incrementDegradationCount,
232
235
  recordDegradationOnce
233
- } from "./chunk-7ELY2CSM.js";
236
+ } from "./chunk-JAU72XNY.js";
234
237
  import {
235
238
  createSubsystemLogger,
236
239
  logExtension
237
- } from "./chunk-34OCDWOS.js";
240
+ } from "./chunk-XTMJ7XDT.js";
238
241
  import {
239
242
  logLatency,
240
243
  phaseFinished,
241
244
  phaseStarted
242
- } from "./chunk-3PNFWVHT.js";
245
+ } from "./chunk-QQNQ7SJW.js";
243
246
  import {
244
247
  createNdjsonLogger,
245
248
  getGlobalPiLensLogDir,
246
249
  getMaxLogSizeMB,
247
250
  isTestMode
248
- } from "./chunk-VSMJK3ZJ.js";
251
+ } from "./chunk-AOHZU2BM.js";
249
252
  import {
250
253
  FactStore,
251
254
  setFactStoreEvictionReporter
252
- } from "./chunk-UGSMCQ4D.js";
255
+ } from "./chunk-CHOW74WE.js";
253
256
  import {
254
257
  BoundedLruCache
255
258
  } from "./chunk-ABBOA7UD.js";
@@ -263,7 +266,7 @@ import {
263
266
  normalizeMapKey,
264
267
  pathsEqual,
265
268
  toProjectRelativePath
266
- } from "./chunk-G3RLJYA2.js";
269
+ } from "./chunk-N2H3ZPZY.js";
267
270
 
268
271
  // dist/clients/mcp/analyze.js
269
272
  import * as fs19 from "node:fs";
@@ -281,6 +284,8 @@ var DEFAULT_TURN_STATE = {
281
284
  };
282
285
  var MCP_TURN_STATE_OWNER_ID = `mcp-${process.pid}`;
283
286
  var TURN_OWNER_STALE_MS = 30 * 60 * 1e3;
287
+ var TURN_SESSION_PARTITION_TTL_MS = 30 * 60 * 1e3;
288
+ var MAX_TURN_SESSION_PARTITIONS = 16;
284
289
  function getLensDir(cwd) {
285
290
  return getProjectDataDir(cwd);
286
291
  }
@@ -521,7 +526,68 @@ var CacheManager = class {
521
526
  /**
522
527
  * Read turn state. Returns default if not found.
523
528
  */
524
- readTurnState(cwd) {
529
+ readTurnState(cwd, sessionId) {
530
+ return this.resolveTurnStatePartition(cwd, sessionId).state;
531
+ }
532
+ /**
533
+ * Reserve a secondary's durable partition at turn start. The legacy
534
+ * envelope may still be ownerless before the first write, so the write
535
+ * itself cannot infer that this session is concurrent from persisted state.
536
+ */
537
+ ensureSecondaryTurnStatePartition(cwd, sessionId) {
538
+ const envelope = this.readTurnStateEnvelope(cwd);
539
+ if (envelope.sessions?.[sessionId])
540
+ return;
541
+ const secondary = {
542
+ ...DEFAULT_TURN_STATE,
543
+ files: {},
544
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
545
+ sessionId,
546
+ owner: {
547
+ kind: "pi",
548
+ id: sessionId,
549
+ pid: process.pid,
550
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString()
551
+ }
552
+ };
553
+ this.writeTurnState({
554
+ ...envelope,
555
+ sessions: { ...envelope.sessions, [sessionId]: secondary }
556
+ }, cwd);
557
+ }
558
+ /** Resolve the persisted primary/secondary turn-state partition. */
559
+ resolveTurnStatePartition(cwd, sessionId) {
560
+ const envelope = this.readTurnStateEnvelope(cwd);
561
+ const persistedSecondary = sessionId === void 0 ? void 0 : envelope.sessions?.[sessionId];
562
+ const primary2 = sessionId === void 0 || envelope.owner === void 0 && persistedSecondary === void 0 || envelope.owner?.kind === "pi" && envelope.owner.id === sessionId;
563
+ const isSecondary = !primary2 && (persistedSecondary !== void 0 || envelope.owner?.kind === "pi" && envelope.owner.pid === process.pid);
564
+ const state = primary2 ? envelope : persistedSecondary ?? {
565
+ ...DEFAULT_TURN_STATE,
566
+ files: {},
567
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
568
+ };
569
+ return {
570
+ envelope,
571
+ state,
572
+ isSecondary,
573
+ persist: (next) => {
574
+ if (isSecondary && sessionId !== void 0) {
575
+ this.writeTurnState({
576
+ ...envelope,
577
+ sessions: { ...envelope.sessions, [sessionId]: next }
578
+ }, cwd);
579
+ } else
580
+ this.writeTurnState(next, cwd);
581
+ },
582
+ remove: () => {
583
+ if (!isSecondary || sessionId === void 0)
584
+ return;
585
+ const { [sessionId]: _retired, ...remaining } = envelope.sessions ?? {};
586
+ this.writeTurnState({ ...envelope, sessions: remaining }, cwd);
587
+ }
588
+ };
589
+ }
590
+ readTurnStateEnvelope(cwd) {
525
591
  const statePath = getTurnStatePath(cwd);
526
592
  if (!fs.existsSync(statePath)) {
527
593
  return {
@@ -531,11 +597,26 @@ var CacheManager = class {
531
597
  };
532
598
  }
533
599
  const state = readJsonCache(statePath, (parsed) => parsed);
534
- return state ?? {
600
+ const envelope = state ?? {
535
601
  ...DEFAULT_TURN_STATE,
536
602
  files: {},
537
603
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
538
604
  };
605
+ if (!envelope.sessions)
606
+ return envelope;
607
+ const now = Date.now();
608
+ const liveEntries = Object.entries(envelope.sessions).filter(([, partition]) => {
609
+ const updated = Date.parse(partition.lastUpdated ?? "");
610
+ return Number.isFinite(updated) && now - updated <= TURN_SESSION_PARTITION_TTL_MS;
611
+ });
612
+ liveEntries.sort(([, left], [, right]) => Date.parse(right.lastUpdated) - Date.parse(left.lastUpdated));
613
+ const sessions = Object.fromEntries(liveEntries.slice(0, MAX_TURN_SESSION_PARTITIONS));
614
+ if (Object.keys(sessions).length !== Object.keys(envelope.sessions).length) {
615
+ const pruned = { ...envelope, sessions };
616
+ writeFileAtomic(statePath, JSON.stringify(pruned, null, 2));
617
+ return pruned;
618
+ }
619
+ return envelope;
539
620
  }
540
621
  /**
541
622
  * Write turn state.
@@ -602,13 +683,17 @@ var CacheManager = class {
602
683
  * current owner; callers must provide an explicit owner id to claim a stale
603
684
  * worklist.
604
685
  */
605
- addModifiedRange(filePath, range, importsChanged, cwd, sessionId, ownerKind = "pi", projectRoot) {
686
+ addModifiedRange(filePath, range, importsChanged, cwd, sessionId, ownerKind = "pi", projectRoot, analysisRootMode) {
687
+ if (analysisRootMode !== void 0 && analysisRootMode !== "session" && analysisRootMode !== "linked-worktree")
688
+ return this.readTurnState(cwd);
606
689
  const containmentRoot = projectRoot ?? cwd;
607
690
  if (!this.isTurnStatePathWithinRoot(filePath, containmentRoot)) {
608
691
  this.log(`turn-state: rejected out-of-project path ${filePath} (project root ${containmentRoot})`);
609
692
  return this.readTurnState(cwd);
610
693
  }
611
- const state = this.readTurnState(cwd);
694
+ const partition = this.resolveTurnStatePartition(cwd, sessionId !== null ? sessionId : void 0);
695
+ const useSessionPartition = partition.isSecondary && ownerKind === "pi" && sessionId != null;
696
+ const state = useSessionPartition ? partition.state : partition.envelope;
612
697
  if (sessionId) {
613
698
  const owner = {
614
699
  kind: ownerKind,
@@ -616,7 +701,7 @@ var CacheManager = class {
616
701
  pid: process.pid,
617
702
  lastSeen: (/* @__PURE__ */ new Date()).toISOString()
618
703
  };
619
- if (this.getTurnStateAccess(cwd, owner) === "foreign-live")
704
+ if (!useSessionPartition && this.getTurnStateAccess(cwd, owner) === "foreign-live")
620
705
  return state;
621
706
  state.sessionId = sessionId;
622
707
  state.owner = owner;
@@ -637,14 +722,23 @@ var CacheManager = class {
637
722
  lastEdit: (/* @__PURE__ */ new Date()).toISOString()
638
723
  };
639
724
  }
640
- this.writeTurnState(state, cwd);
725
+ if (useSessionPartition)
726
+ partition.persist(state);
727
+ else
728
+ this.writeTurnState(state, cwd);
641
729
  return state;
642
730
  }
643
731
  /**
644
732
  * Clear turn state (after turn_end processes it).
645
733
  */
646
- clearTurnState(cwd, owner) {
647
- const currentState = this.readTurnState(cwd);
734
+ clearTurnState(cwd, owner, sessionId) {
735
+ const partition = this.resolveTurnStatePartition(cwd, sessionId);
736
+ if (sessionId !== void 0 && partition.isSecondary) {
737
+ if (partition.envelope.sessions?.[sessionId])
738
+ partition.remove();
739
+ return true;
740
+ }
741
+ const currentState = partition.envelope;
648
742
  const isCurrentOwner = this.getTurnStateAccess(cwd, owner) !== "foreign-live";
649
743
  if (!isCurrentOwner && process.pid !== currentState.owner?.pid)
650
744
  return false;
@@ -668,35 +762,38 @@ var CacheManager = class {
668
762
  /**
669
763
  * Increment turn cycle counter.
670
764
  */
671
- incrementTurnCycle(cwd, owner) {
672
- const state = this.readTurnState(cwd);
765
+ incrementTurnCycle(cwd, owner, sessionId) {
766
+ const partition = this.resolveTurnStatePartition(cwd, sessionId);
767
+ const state = partition.state;
768
+ if (sessionId !== void 0 && state.owner?.id !== sessionId)
769
+ return state;
673
770
  const isCurrentOwner = this.getTurnStateAccess(cwd, owner) !== "foreign-live";
674
771
  if (!isCurrentOwner && process.pid !== state.owner?.pid)
675
772
  return state;
676
773
  state.turnCycles++;
677
- this.writeTurnState(state, cwd);
774
+ partition.persist(state);
678
775
  return state;
679
776
  }
680
777
  /**
681
778
  * Check if max cycles exceeded.
682
779
  */
683
- isMaxCyclesExceeded(cwd) {
684
- const state = this.readTurnState(cwd);
780
+ isMaxCyclesExceeded(cwd, sessionId) {
781
+ const state = this.readTurnState(cwd, sessionId);
685
782
  return state.turnCycles >= state.maxCycles;
686
783
  }
687
784
  /**
688
785
  * Get files that need jscpd re-scan (any edit).
689
786
  * Only returns source code files jscpd can meaningfully analyse.
690
787
  */
691
- getFilesForJscpd(cwd) {
692
- const state = this.readTurnState(cwd);
788
+ getFilesForJscpd(cwd, sessionId) {
789
+ const state = this.readTurnState(cwd, sessionId);
693
790
  return Object.keys(state.files).filter((f) => /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|rb|java|cs|php|cpp|c|h|hpp|swift|kt)$/.test(f));
694
791
  }
695
792
  /**
696
793
  * Get files that need madge re-scan (imports changed).
697
794
  */
698
- getFilesForMadge(cwd) {
699
- const state = this.readTurnState(cwd);
795
+ getFilesForMadge(cwd, sessionId) {
796
+ const state = this.readTurnState(cwd, sessionId);
700
797
  return Object.entries(state.files).filter(([, f]) => f.importsChanged).map(([p]) => p);
701
798
  }
702
799
  // ---- Utilities ----
@@ -1084,6 +1181,11 @@ var LANGUAGE_CAPABILITY_MATRIX = {
1084
1181
  { mode: "fallback", runnerIds: ["detekt"], filterKinds: ["kotlin"] }
1085
1182
  ]
1086
1183
  },
1184
+ lean: {
1185
+ name: "Lean 4 Diagnostics",
1186
+ capabilities: ["types", "lint"],
1187
+ writeGroups: [primary("lean")]
1188
+ },
1087
1189
  swift: {
1088
1190
  name: "Swift Linting",
1089
1191
  capabilities: ["types", "lint"],
@@ -1209,6 +1311,7 @@ function settledSnapshot(entry) {
1209
1311
  // #3758/#3813: carry the producer's handle so a requeued snapshot keeps
1210
1312
  // the scope that owned it, and the gate's peek can fence with it.
1211
1313
  session: entry.session,
1314
+ sessionId: entry.sessionId,
1212
1315
  result: entry.result
1213
1316
  };
1214
1317
  }
@@ -1219,12 +1322,17 @@ function ownedByLiveSession(entry, site) {
1219
1322
  return entry.session.guardedWrite(`${site}:${entry.runnerId}:${entry.filePath}`, () => true) !== void 0;
1220
1323
  }
1221
1324
  function deferRunnerFindings(entry) {
1222
- const { session, ...owned } = entry;
1325
+ const { session, sessionId, ...owned } = entry;
1223
1326
  if (session !== void 0 && session.guardedWrite(`${entry.runnerId}:${entry.filePath}`, () => true) === void 0) {
1224
1327
  void entry.promise.catch(() => void 0);
1225
1328
  return;
1226
1329
  }
1227
- const tracked = { ...owned, session, settled: false };
1330
+ const tracked = {
1331
+ ...owned,
1332
+ session,
1333
+ sessionId,
1334
+ settled: false
1335
+ };
1228
1336
  void tracked.promise.then((result) => {
1229
1337
  tracked.result = result;
1230
1338
  tracked.settled = true;
@@ -1245,6 +1353,7 @@ function requeueRunnerFindings(entry) {
1245
1353
  track({
1246
1354
  ...owned,
1247
1355
  session: entry.session,
1356
+ sessionId: entry.sessionId,
1248
1357
  promise: Promise.resolve(result),
1249
1358
  settled: true,
1250
1359
  result
@@ -1263,7 +1372,7 @@ function track(tracked) {
1263
1372
  }
1264
1373
  }
1265
1374
  }
1266
- async function drainPendingRunnerFindings(maxWaitMs = 2e3) {
1375
+ async function drainPendingRunnerFindings(maxWaitMs = 2e3, currentSession, currentSessionId) {
1267
1376
  if (pending.length === 0)
1268
1377
  return [];
1269
1378
  const current = pending.splice(0, pending.length);
@@ -1279,6 +1388,14 @@ async function drainPendingRunnerFindings(maxWaitMs = 2e3) {
1279
1388
  for (const entry of current) {
1280
1389
  if (!ownedByLiveSession(entry, "turn-end"))
1281
1390
  continue;
1391
+ if (currentSessionId !== void 0 && entry.sessionId !== void 0 && entry.sessionId !== currentSessionId) {
1392
+ pending.push(entry);
1393
+ continue;
1394
+ }
1395
+ if (currentSession !== void 0 && entry.session !== void 0 && entry.session.generation !== currentSession.generation) {
1396
+ pending.push(entry);
1397
+ continue;
1398
+ }
1282
1399
  if (entry.settled && entry.result) {
1283
1400
  results.push(settledSnapshot(entry));
1284
1401
  } else {
@@ -1304,6 +1421,26 @@ function pendingRunnerFindingsSize() {
1304
1421
  }
1305
1422
 
1306
1423
  // dist/clients/dispatch/rule-policy.js
1424
+ function resolvedRulePolicyMap(root) {
1425
+ const resolved = resolvePiLensConfig({
1426
+ cwd: root,
1427
+ globalDir: getGlobalPiLensDir(),
1428
+ globalConfigPath: getPiLensGlobalConfigPath()
1429
+ });
1430
+ return rulePolicyMapFromConfig(resolved.value.rules);
1431
+ }
1432
+ function ruleIgnoredForPath(ruleId, filePath, root, policyMap) {
1433
+ const normalized = normalizeRuleId(ruleId);
1434
+ const patterns = [];
1435
+ for (const [configuredId, entry] of Object.entries(policyMap ?? {})) {
1436
+ if (normalizeRuleId(configuredId) !== normalized || !entry?.ignorePaths)
1437
+ continue;
1438
+ patterns.push(...entry.ignorePaths);
1439
+ }
1440
+ if (patterns.length === 0)
1441
+ return false;
1442
+ return isRuleIgnoredForPath(filePath, root, patterns);
1443
+ }
1307
1444
  function evaluateRulePolicy(ruleId, policyMap) {
1308
1445
  if (!policyMap)
1309
1446
  return { dropped: false };
@@ -1331,7 +1468,7 @@ function matchesRule(entry, raw, normalized) {
1331
1468
  return true;
1332
1469
  return normalizeRuleId(entry) === normalized;
1333
1470
  }
1334
- function applyRulePolicy(diagnostics, policyMap) {
1471
+ function applyRulePolicy(diagnostics, policyMap, options) {
1335
1472
  if (!policyMap)
1336
1473
  return diagnostics;
1337
1474
  let hasFilter = false;
@@ -1340,7 +1477,7 @@ function applyRulePolicy(diagnostics, policyMap) {
1340
1477
  continue;
1341
1478
  }
1342
1479
  const entry = rawEntry;
1343
- if ((entry.disable?.length ?? 0) > 0 || (entry.select?.length ?? 0) > 0) {
1480
+ if ((entry.disable?.length ?? 0) > 0 || (entry.select?.length ?? 0) > 0 || (entry.ignorePaths?.length ?? 0) > 0) {
1344
1481
  hasFilter = true;
1345
1482
  break;
1346
1483
  }
@@ -1351,6 +1488,9 @@ function applyRulePolicy(diagnostics, policyMap) {
1351
1488
  const ruleId = d.rule ?? d.code;
1352
1489
  if (!ruleId)
1353
1490
  return true;
1491
+ const filePath = d.filePath ?? options.filePath;
1492
+ if (filePath && ruleIgnoredForPath(ruleId, filePath, options.root, policyMap))
1493
+ return false;
1354
1494
  const { dropped } = evaluateRulePolicy(ruleId, policyMap);
1355
1495
  return !dropped;
1356
1496
  });
@@ -1366,12 +1506,14 @@ function rulePolicyMapFromConfig(rules2) {
1366
1506
  const entry = rawEntry;
1367
1507
  const hasDisable = (entry.disable?.length ?? 0) > 0;
1368
1508
  const hasSelect = (entry.select?.length ?? 0) > 0;
1369
- if (!hasDisable && !hasSelect)
1509
+ const hasIgnorePaths = (entry.ignorePaths?.length ?? 0) > 0;
1510
+ if (!hasDisable && !hasSelect && !hasIgnorePaths)
1370
1511
  continue;
1371
1512
  built ??= {};
1372
1513
  built[key2] = {
1373
1514
  ...hasDisable ? { disable: entry.disable } : {},
1374
- ...hasSelect ? { select: entry.select } : {}
1515
+ ...hasSelect ? { select: entry.select } : {},
1516
+ ...hasIgnorePaths ? { ignorePaths: entry.ignorePaths } : {}
1375
1517
  };
1376
1518
  }
1377
1519
  return built;
@@ -1611,7 +1753,7 @@ function readFilePrefix(filePath, maxBytes = 4096) {
1611
1753
  }
1612
1754
  }
1613
1755
  }
1614
- function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedRanges, projectRoot, writeIndex, telemetryModel, telemetryProvider, sessionGeneration) {
1756
+ function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedRanges, projectRoot, writeIndex, telemetryModel, telemetryProvider, sessionGeneration, sessionId, analysisRootMode) {
1615
1757
  const absoluteFilePath = resolveRunnerPath(cwd, filePath);
1616
1758
  const normalizedProjectRoot = normalizeMapKey(path4.resolve(projectRoot ?? cwd));
1617
1759
  const normalizedCwd = normalizeMapKey(resolveLanguageRootForFile(absoluteFilePath, cwd));
@@ -1625,12 +1767,14 @@ function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedR
1625
1767
  includeDeclarations: false
1626
1768
  }) : void 0;
1627
1769
  const projectConfig = loadPiLensProjectConfig(normalizedCwd);
1770
+ const rulePolicy = resolvedRulePolicyMap(normalizedProjectRoot);
1628
1771
  return {
1629
1772
  filePath: normalizedFilePath,
1630
1773
  projectRoot: normalizedProjectRoot,
1631
1774
  cwd: normalizedCwd,
1632
1775
  kind,
1633
1776
  fileRole,
1777
+ analysisRootMode,
1634
1778
  generatedEvidence: generatedDetail?.evidence,
1635
1779
  generatedLineShapeMean: generatedDetail?.lineShapeMean,
1636
1780
  pi,
@@ -1638,10 +1782,12 @@ function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedR
1638
1782
  deltaMode: !pi.getFlag("no-delta"),
1639
1783
  facts,
1640
1784
  projectConfig,
1785
+ rulePolicy,
1641
1786
  blockingOnly,
1642
1787
  modifiedRanges,
1643
1788
  writeIndex,
1644
1789
  sessionGeneration,
1790
+ sessionId,
1645
1791
  telemetryModel,
1646
1792
  telemetryProvider,
1647
1793
  toolCwdMemo: {},
@@ -2028,7 +2174,8 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
2028
2174
  markedAtMs,
2029
2175
  writeIndex: ctx.writeIndex,
2030
2176
  promise: deferred,
2031
- session: ctx.sessionGeneration
2177
+ session: ctx.sessionGeneration,
2178
+ sessionId: ctx.sessionId
2032
2179
  });
2033
2180
  latencies.push({
2034
2181
  runnerId: runner.id,
@@ -2140,6 +2287,19 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
2140
2287
  }
2141
2288
  async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
2142
2289
  const _overallStart = Date.now();
2290
+ if (ctx.analysisRootMode === "adopted") {
2291
+ return {
2292
+ diagnostics: [],
2293
+ blockers: [],
2294
+ warnings: [],
2295
+ baselineWarningCount: 0,
2296
+ fixed: [],
2297
+ resolvedCount: 0,
2298
+ output: "",
2299
+ blockerOutput: "",
2300
+ hasBlockers: false
2301
+ };
2302
+ }
2143
2303
  if (ctx.fileRole === "generated") {
2144
2304
  const evidence = ctx.generatedEvidence;
2145
2305
  const lineShapeMean = ctx.generatedLineShapeMean;
@@ -2204,13 +2364,16 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
2204
2364
  }
2205
2365
  const dedupedDiagnostics = dedupeOverlappingDiagnostics(allDiagnostics);
2206
2366
  const fileContent = ctx.facts.getFileFact(ctx.filePath, "file.content") ?? "";
2207
- const rulePolicy = rulePolicyMapFromConfig(loadPiLensProjectConfig(ctx.projectRoot ?? ctx.cwd).rules);
2367
+ const rulePolicy = ctx.rulePolicy ?? rulePolicyMapFromConfig(loadPiLensProjectConfig(ctx.projectRoot ?? ctx.cwd).rules);
2208
2368
  const applyOutputFilters = (diags) => {
2209
2369
  const dockerOverlap = suppressTrivyConfigDockerOverlap(diags);
2210
2370
  const overlap = suppressLintOverlapsWithLsp(dockerOverlap);
2211
2371
  const inline = applyInlineSuppressions(overlap, fileContent);
2212
2372
  const disposition = applyDispositions(inline, ctx.projectRoot ?? ctx.cwd, ctx.filePath, fileContent);
2213
- return applyRulePolicy(disposition, rulePolicy);
2373
+ return applyRulePolicy(disposition, rulePolicy, {
2374
+ root: ctx.projectRoot ?? ctx.cwd,
2375
+ filePath: ctx.filePath
2376
+ });
2214
2377
  };
2215
2378
  let visibleDiagnostics = applyOutputFilters(dedupedDiagnostics);
2216
2379
  let resolvedCount = 0;
@@ -2230,14 +2393,14 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
2230
2393
  provider: ctx.telemetryProvider
2231
2394
  };
2232
2395
  if (fixedItems.length > 0) {
2233
- import("./chunk-3JL6IFD7.js").then(({ appendToWorklog }) => {
2396
+ import("./chunk-6SDEP3AJ.js").then(({ appendToWorklog }) => {
2234
2397
  appendToWorklog(ctx.cwd, fixedItems, true, worklogIdentity);
2235
2398
  }).catch(() => {
2236
2399
  });
2237
2400
  }
2238
2401
  const fixableWarnings = warnings.filter((d) => d.fixable);
2239
2402
  if (fixableWarnings.length > 0) {
2240
- import("./chunk-3JL6IFD7.js").then(({ appendToWorklog }) => {
2403
+ import("./chunk-6SDEP3AJ.js").then(({ appendToWorklog }) => {
2241
2404
  appendToWorklog(ctx.cwd, fixableWarnings, false, worklogIdentity);
2242
2405
  }).catch(() => {
2243
2406
  });
@@ -2431,10 +2594,16 @@ function convertLspDiagnostics(diags, filePath, options = {}) {
2431
2594
  function applyFindingPolicy(diagnostics, options) {
2432
2595
  const inlineKept = applyInlineSuppressions(diagnostics, options.content);
2433
2596
  const disposed = filterDisposed(inlineKept, options);
2434
- return { kept: applyRulePolicy(disposed, options.policyMap), inlineKept };
2597
+ return {
2598
+ kept: applyRulePolicy(disposed, options.policyMap, {
2599
+ root: options.cwd,
2600
+ filePath: options.filePath
2601
+ }),
2602
+ inlineKept
2603
+ };
2435
2604
  }
2436
2605
  function loadProjectRulePolicyMap(cwd) {
2437
- return rulePolicyMapFromConfig(loadPiLensProjectConfig(cwd).rules);
2606
+ return resolvedRulePolicyMap(cwd);
2438
2607
  }
2439
2608
  function filterDisposed(diagnostics, options) {
2440
2609
  const identities = options.identities;
@@ -2605,6 +2774,9 @@ function formatCacheAgeLabel(scannedAt, nowMs = Date.now()) {
2605
2774
  const remMinutes = ageMinutes % 60;
2606
2775
  return remMinutes === 0 ? `scanned ${ageHours}h ago` : `scanned ${ageHours}h ${remMinutes}m ago`;
2607
2776
  }
2777
+ function admitsProjectWideFindings(sessionRole) {
2778
+ return sessionRole === "primary";
2779
+ }
2608
2780
  function gated(file, description, gates, evidence, extra = {}) {
2609
2781
  return { mode: "gated", file, description, gates, evidence, ...extra };
2610
2782
  }
@@ -3443,6 +3615,8 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
3443
3615
  continue;
3444
3616
  if (catalog.effectiveRules.get(rule.id)?.rule !== rule)
3445
3617
  continue;
3618
+ if (ruleIgnoredForPath(rule.id, filePath, ignoreRoot, options.rulePolicy))
3619
+ continue;
3446
3620
  if (blockingOnly && rule.severity !== "error")
3447
3621
  continue;
3448
3622
  if (isRuleIgnoredForPath(filePath, ignoreRoot, rule.ignores))
@@ -3632,6 +3806,7 @@ var astGrepNapiRunner = {
3632
3806
  const diagnostics = evaluateAstGrepRules(ctx.filePath, rootNode, ctx.cwd, ctx.kind, {
3633
3807
  blockingOnly: runningAsLspSubstitute ? false : ctx.blockingOnly,
3634
3808
  projectRoot: ctx.projectRoot,
3809
+ rulePolicy: ctx.rulePolicy,
3635
3810
  log: (message) => ctx.log(message),
3636
3811
  content,
3637
3812
  sgModule
@@ -7293,7 +7468,7 @@ var OXLINT_NO_FILES_REPORT_KEYS = /* @__PURE__ */ new Set([
7293
7468
  "start_time"
7294
7469
  ]);
7295
7470
  function resolveLocalVp(cwd) {
7296
- return findLocalBinUpwards("vp", cwd) ?? null;
7471
+ return localBinPath(findLocalBinUpwards("vp", cwd)) ?? null;
7297
7472
  }
7298
7473
  async function resolveVitePlusCommand(cwd) {
7299
7474
  const local = resolveLocalVp(cwd);
@@ -7765,7 +7940,13 @@ var prismaValidateRunner = {
7765
7940
  const cwd = resolveRunnerCwd(ctx, "prisma-validate");
7766
7941
  const resolved = await resolveLocalFirstAsync("prisma", cwd);
7767
7942
  const absPath = path32.resolve(cwd, ctx.filePath);
7768
- const result = await safeSpawnAsync(resolved.cmd, [...resolved.args, "validate", "--schema", absPath], { timeout: 2e4, cwd });
7943
+ const result = await safeSpawnAsync(resolved.cmd, [...resolved.args, "validate", "--schema", absPath], {
7944
+ timeout: 2e4,
7945
+ // ONE neutral-cwd seam for npx fallbacks (#4193, #4268 acceptance 3),
7946
+ // an override of the resolver's project cwd that the scan can still see.
7947
+ cwd,
7948
+ ...resolved.cmd === "npx" ? getIsolatedNpxSpawnOptions() : {}
7949
+ });
7769
7950
  if (result.error && !result.stdout && !result.stderr) {
7770
7951
  return { status: "skipped", diagnostics: [], semantic: "none" };
7771
7952
  }
@@ -8120,7 +8301,7 @@ var pyrightRunner = {
8120
8301
  cmd = installedPath;
8121
8302
  }
8122
8303
  if (!cmd) {
8123
- const { findCommandAsync } = await import("./chunk-BHWHXMQ2.js");
8304
+ const { findCommandAsync } = await import("./chunk-67WMNWEE.js");
8124
8305
  const foundCmd = await findCommandAsync("pyright");
8125
8306
  if (foundCmd)
8126
8307
  cmd = foundCmd;
@@ -9570,7 +9751,7 @@ var taploRunner = {
9570
9751
  claimSource: cover.claimSource
9571
9752
  };
9572
9753
  }
9573
- let cmd = findLocalBinUpwards("taplo", cwd) ?? null;
9754
+ let cmd = localBinPath(findLocalBinUpwards("taplo", cwd)) ?? null;
9574
9755
  if (!cmd) {
9575
9756
  if (await taplo.isAvailableAsync(cwd)) {
9576
9757
  cmd = taplo.getCommand(cwd);
@@ -10528,7 +10709,7 @@ var treeSitterRunner = {
10528
10709
  }
10529
10710
  const fileIsTest = isTestFile(filePath);
10530
10711
  const ignoreRoot = ctx.projectRoot ?? ctx.cwd;
10531
- const effectiveQueries = (ctx.blockingOnly ? languageQueries.filter((q) => q.inline_tier !== "review") : languageQueries).filter((q) => !(fileIsTest && q.skip_test_files) && !isRuleIgnoredForPath(filePath, ignoreRoot, q.ignore_paths));
10712
+ const effectiveQueries = (ctx.blockingOnly ? languageQueries.filter((q) => q.inline_tier !== "review") : languageQueries).filter((q) => !(fileIsTest && q.skip_test_files) && !isRuleIgnoredForPath(filePath, ignoreRoot, q.ignore_paths) && !ruleIgnoredForPath(q.id, filePath, ignoreRoot, ctx.rulePolicy));
10532
10713
  logTreeSitter({
10533
10714
  phase: "queries_loaded",
10534
10715
  filePath,
@@ -10538,6 +10719,9 @@ var treeSitterRunner = {
10538
10719
  cacheHit,
10539
10720
  metadata: { blockingOnly: !!ctx.blockingOnly }
10540
10721
  });
10722
+ if (effectiveQueries.length === 0) {
10723
+ return { status: "succeeded", diagnostics: [], semantic: "none" };
10724
+ }
10541
10725
  const contentFromFacts = ctx.facts.getFileFact(filePath, "file.content");
10542
10726
  const contentOverride = contentFromFacts !== void 0 && contentFromFacts !== null ? contentFromFacts : void 0;
10543
10727
  const diagnostics = [];
@@ -11727,7 +11911,7 @@ var CASCADE_GRAPH_KINDS = /* @__PURE__ */ new Set([
11727
11911
  "cxx"
11728
11912
  ]);
11729
11913
  async function dispatchLintWithResult(filePath, cwd, pi, modifiedRanges, logContext, options) {
11730
- const ctx = createDispatchContext(filePath, cwd, pi, sessionFacts, options?.blockingOnly ?? true, modifiedRanges, options?.projectRoot, options?.writeIndex, options?.telemetryModel, options?.telemetryProvider, options?.sessionGeneration);
11914
+ const ctx = createDispatchContext(filePath, cwd, pi, sessionFacts, options?.blockingOnly ?? true, modifiedRanges, options?.projectRoot, options?.writeIndex, options?.telemetryModel, options?.telemetryProvider, options?.sessionGeneration, options?.sessionId, options?.analysisRootMode);
11731
11915
  sessionFacts.clearFileFactsFor(ctx.filePath);
11732
11916
  try {
11733
11917
  const kind = ctx.kind;
@@ -12097,6 +12281,7 @@ export {
12097
12281
  filterFindingsByDisposition,
12098
12282
  markUnreconciledFindings,
12099
12283
  formatCacheAgeLabel,
12284
+ admitsProjectWideFindings,
12100
12285
  cascadeCarrySuffix,
12101
12286
  logCascade,
12102
12287
  resetCascadeTierSessionState,