pi-lens 4.4.3 → 4.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +281 -0
- package/README.md +13 -1
- package/dist/{chunk-SS36ZX4J.js → chunk-24AKHFGP.js} +6 -6
- package/dist/{chunk-JSQFTSC6.js → chunk-2FN63LPV.js} +11 -11
- package/dist/{chunk-5UCAH366.js → chunk-2KXTHF3M.js} +20 -20
- package/dist/{chunk-EU63SDCG.js → chunk-3DA2JDOL.js} +367 -281
- package/dist/{chunk-RWWYJ623.js → chunk-3KAZU3VR.js} +1 -1
- package/dist/chunk-3PTHXJXR.js +28 -0
- package/dist/chunk-3QED2P4V.js +31 -0
- package/dist/{chunk-N2H3ZPZY.js → chunk-3RKP3FMS.js} +1 -0
- package/dist/{chunk-XVF2VVXP.js → chunk-5HSRT26B.js} +2 -2
- package/dist/{chunk-MXGY6KPT.js → chunk-5IUSNGOC.js} +15 -15
- package/dist/{chunk-EJIUXPBX.js → chunk-5OFV52AM.js} +1 -1
- package/dist/{chunk-AW7R2GWG.js → chunk-5VSF4UUQ.js} +12 -7
- package/dist/{chunk-6STA6Z7I.js → chunk-5WRPDP2A.js} +18 -18
- package/dist/{chunk-YIUAVF7E.js → chunk-6DLWKFEX.js} +35 -34
- package/dist/{chunk-WOA4LN2R.js → chunk-7D6L4MTX.js} +2 -2
- package/dist/{chunk-GAEGEPOC.js → chunk-7HXE67BN.js} +2 -2
- package/dist/chunk-AGSS7277.js +84 -0
- package/dist/{chunk-R3PCY3YS.js → chunk-AMERCH6V.js} +13 -13
- package/dist/{chunk-WU567RSC.js → chunk-ATKJFDQN.js} +14 -10
- package/dist/{chunk-VSSBEUFT.js → chunk-AWSCPCN2.js} +16 -16
- package/dist/{chunk-VCHXCQFG.js → chunk-BWD5EPKO.js} +3 -3
- package/dist/{chunk-H6MF6EVN.js → chunk-CT4MN5IU.js} +1200 -230
- package/dist/{chunk-FCSOVF55.js → chunk-CUHSHSB6.js} +6 -6
- package/dist/{chunk-CHOW74WE.js → chunk-CYRKQRPM.js} +7 -10
- package/dist/{chunk-Q7DUK4LX.js → chunk-DEL2U6CM.js} +5 -5
- package/dist/{chunk-6C7JWPCP.js → chunk-DGUKIYSI.js} +26 -23
- package/dist/{chunk-PHDMFAKM.js → chunk-DUO2TU77.js} +2 -2
- package/dist/{chunk-MRXKYPCS.js → chunk-EBC36LNN.js} +2 -2
- package/dist/{chunk-CSHFH5IN.js → chunk-ED36RF6Y.js} +1 -1
- package/dist/{chunk-76MWC2K6.js → chunk-EUXZEFTV.js} +90 -97
- package/dist/{chunk-QOZXJ4NA.js → chunk-FM4RDMKT.js} +11 -8
- package/dist/{chunk-ACXEQZOU.js → chunk-GAQ7OQG6.js} +31 -28
- package/dist/{chunk-XAGLWMJ4.js → chunk-GL5LUMZE.js} +23 -23
- package/dist/{chunk-BKE7E7TC.js → chunk-GMX5OS7B.js} +9 -9
- package/dist/{chunk-ZHFZWTZV.js → chunk-GSLNCYGG.js} +11 -11
- package/dist/{chunk-3W7IEVVL.js → chunk-GSM5UU7A.js} +26 -34
- package/dist/{chunk-724UL2TJ.js → chunk-GXFV6MYU.js} +3 -3
- package/dist/chunk-HAD7QRQI.js +30 -0
- package/dist/{chunk-QOBUHWHX.js → chunk-HRNHZA3N.js} +6 -6
- package/dist/{chunk-VWCXW2E7.js → chunk-HWCCCQNX.js} +1 -1
- package/dist/{chunk-7DYBLXYA.js → chunk-HYGZEMX6.js} +3 -3
- package/dist/chunk-IJYGIDF4.js +186 -0
- package/dist/{chunk-4W4VLAPJ.js → chunk-IQWN5JCP.js} +11 -11
- package/dist/{chunk-SQ4TVJBR.js → chunk-IUE7SSKV.js} +7 -7
- package/dist/{chunk-IBGIOBEE.js → chunk-IWDLU6K3.js} +68 -5
- package/dist/{chunk-XCJN5IJU.js → chunk-IYNJ6YPZ.js} +4 -4
- package/dist/{chunk-JAU72XNY.js → chunk-J64T55EI.js} +3 -3
- package/dist/{chunk-2BBLFX75.js → chunk-J6MPGQTS.js} +5 -5
- package/dist/chunk-JORED7EX.js +44 -0
- package/dist/{chunk-6SDEP3AJ.js → chunk-JUKMK5Y4.js} +8 -8
- package/dist/{chunk-FMSO6RDZ.js → chunk-JW3YWBVB.js} +15 -15
- package/dist/{chunk-L3BLXZG7.js → chunk-KAPJINKN.js} +30 -69
- package/dist/{chunk-2B73ZPOK.js → chunk-KN35K52N.js} +3 -3
- package/dist/{chunk-C34ZXZ7O.js → chunk-KUA4OJ5Y.js} +24 -11
- package/dist/chunk-KYUB6QDC.js +72 -0
- package/dist/{chunk-67WMNWEE.js → chunk-LLJNQKQW.js} +12 -10
- package/dist/chunk-LZSEQW6A.js +57 -0
- package/dist/{chunk-ZANLILYD.js → chunk-M2IFVFWU.js} +2 -2
- package/dist/chunk-M2UD3LPU.js +88 -0
- package/dist/{chunk-XIJZVPD5.js → chunk-MBKQHGA7.js} +15 -15
- package/dist/{chunk-P7266HLM.js → chunk-MPNJLASA.js} +2 -2
- package/dist/{chunk-6GFRNVYR.js → chunk-MZGQNL3Y.js} +10 -10
- package/dist/{chunk-ZWFS3OEF.js → chunk-N5FLEO7W.js} +33 -32
- package/dist/{chunk-3JNKMP3B.js → chunk-O4NWQT6I.js} +4 -4
- package/dist/{chunk-T6CPIZNT.js → chunk-OHKJ7PQF.js} +33 -32
- package/dist/{chunk-VRZP76YM.js → chunk-P63GXC37.js} +4 -1
- package/dist/{chunk-XTMJ7XDT.js → chunk-POMLXPMY.js} +1 -1
- package/dist/{chunk-QQNQ7SJW.js → chunk-QBFBRV2B.js} +10 -4
- package/dist/{chunk-CMMHNUZ2.js → chunk-R3T7CLQ2.js} +60 -38
- package/dist/{chunk-23WOO7TX.js → chunk-R7YOCSNV.js} +10 -10
- package/dist/{chunk-2CD5RS6M.js → chunk-RKBXZN3A.js} +23 -2
- package/dist/{chunk-OCAGUNBC.js → chunk-RKKOYPRA.js} +12 -12
- package/dist/{chunk-52FUZI6K.js → chunk-RMLC67LF.js} +1 -1
- package/dist/{chunk-XMSXXAHW.js → chunk-ROYSX2S5.js} +2 -2
- package/dist/{chunk-M6HSLBWY.js → chunk-RVK72CZX.js} +6507 -7514
- package/dist/{chunk-FLKWCIZH.js → chunk-S2HEXIWI.js} +5 -5
- package/dist/{chunk-UZ3TUTRV.js → chunk-S67KYG37.js} +1 -1
- package/dist/{chunk-VCO24T4L.js → chunk-SD4I7ZO4.js} +14 -14
- package/dist/{chunk-Z527N6YQ.js → chunk-SKAMFC7A.js} +12 -12
- package/dist/{chunk-MQLUAEOC.js → chunk-SRYEJNES.js} +2 -2
- package/dist/{chunk-BRGDSBJE.js → chunk-SYE6T2EB.js} +12 -12
- package/dist/{chunk-GXW6K4YJ.js → chunk-T57LYLZT.js} +1 -1
- package/dist/{chunk-ZXYDQ3TZ.js → chunk-T7FEBKXN.js} +48 -15
- package/dist/{chunk-3EFKIGZN.js → chunk-TIQ2PKDW.js} +3 -3
- package/dist/{chunk-QILIYSJF.js → chunk-TLX72JTG.js} +1 -1
- package/dist/{chunk-TYM6OUIT.js → chunk-TOY6QKOH.js} +12 -12
- package/dist/{chunk-IZSHAIJ7.js → chunk-TRETHTQO.js} +12 -12
- package/dist/{chunk-3VPVG5SU.js → chunk-U44DJXQP.js} +10 -6
- package/dist/{chunk-PNQDPDRC.js → chunk-UA7ZXYDR.js} +1 -1
- package/dist/{chunk-OXXKQCSV.js → chunk-UBOQLVT2.js} +4 -4
- package/dist/{chunk-QGQ5CCCG.js → chunk-UMS2MFPZ.js} +2 -2
- package/dist/{chunk-QHJ6DQ2R.js → chunk-US7ECLD7.js} +55 -13
- package/dist/{chunk-AB3YYG6N.js → chunk-UZ2XCLYS.js} +8 -8
- package/dist/chunk-V35JG4JB.js +2667 -0
- package/dist/{chunk-N3X6Q4YT.js → chunk-VOOAPROD.js} +3 -3
- package/dist/{chunk-SAEFPSB6.js → chunk-W66O5E25.js} +21 -11
- package/dist/{chunk-KBG47GHP.js → chunk-WMYE35PX.js} +15 -11
- package/dist/{chunk-5NGR67U5.js → chunk-XBJVAEEO.js} +32 -5
- package/dist/{chunk-YYOIQFRS.js → chunk-XHJBS436.js} +122 -44
- package/dist/{chunk-GBPP5P7X.js → chunk-XTBDCR27.js} +4 -4
- package/dist/{chunk-4UNXBNE2.js → chunk-XTFDJI3T.js} +11 -11
- package/dist/{chunk-UXGETRP4.js → chunk-XYURS6EN.js} +13 -12
- package/dist/{chunk-RPLINGVB.js → chunk-Y6GZHWSJ.js} +6 -6
- package/dist/{chunk-2VUQMUMT.js → chunk-YCWYO6TQ.js} +41 -38
- package/dist/{chunk-77M37OKR.js → chunk-YH5MVY2U.js} +7 -7
- package/dist/{chunk-AOHZU2BM.js → chunk-YNE3RP52.js} +1 -1
- package/dist/{chunk-YSZNHOBY.js → chunk-ZHH37KZL.js} +12 -12
- package/dist/{chunk-ZGDGW2V3.js → chunk-ZIVJBOO3.js} +2 -2
- package/dist/{chunk-RXCOMYPY.js → chunk-ZVUL7QYY.js} +29 -28
- package/dist/index.js +11052 -5852
- package/dist/mcp/analyze-cli.js +10 -9
- package/dist/mcp/cli.js +41 -38
- package/dist/mcp/server.js +1120 -474
- package/dist/mcp/worker.js +61 -58
- package/dist/probes/installer.js +19 -19
- package/dist/workers/project-snapshot-persist-worker.js +28 -9
- package/dist/workers/review-graph-persist-worker.js +1 -1
- package/docs/configuration.md +11 -0
- package/docs/engineering-principles.md +32 -0
- package/docs/lsp-capability-matrix.md +1 -1
- package/docs/lsp-idle-eviction.md +15 -26
- package/docs/pi-lens-fixer.md +117 -13
- package/docs/pi-lens-merge-policy.md +97 -7
- package/docs/pi-lens-monitor.md +8 -2
- package/docs/pi-lens-retro.md +4 -1
- package/docs/pi-lens-reviewer.md +112 -4
- package/docs/pi-lens-subagent.md +22 -14
- package/docs/release-qa-baseline.md +3 -1
- package/docs/servercapabilities.md +9 -19
- package/package.json +7 -5
- package/scripts/download-grammars.js +40 -7
- package/scripts/lib/latency-log-phases.mjs +95 -0
- package/scripts/rpc-load-check.mjs +570 -81
- package/dist/chunk-3YN6V5TV.js +0 -85
- package/dist/chunk-466Z26MG.js +0 -30
- package/dist/chunk-EC47DWFA.js +0 -56
- package/dist/chunk-KDERNTCQ.js +0 -28
- package/dist/chunk-KSX3TXSZ.js +0 -69
- package/dist/chunk-LOP6GRPH.js +0 -31
- package/dist/chunk-UOPVJQ4N.js +0 -103
- /package/dist/{chunk-FC4RP4I2.js → chunk-6HWVI6MI.js} +0 -0
|
@@ -2,7 +2,7 @@ import { createRequire as __pilensCreateRequire } from "node:module"; const requ
|
|
|
2
2
|
import {
|
|
3
3
|
getLazyInstallAttempt,
|
|
4
4
|
tryLazyInstall
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UBOQLVT2.js";
|
|
6
6
|
import {
|
|
7
7
|
findingsResult,
|
|
8
8
|
finishParsedRun,
|
|
@@ -11,24 +11,29 @@ import {
|
|
|
11
11
|
isRunnerClaimSource,
|
|
12
12
|
isRunnerSkipReason,
|
|
13
13
|
parseToolRun,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
reachedNoVerdict,
|
|
15
|
+
skipUnlessToolRan,
|
|
16
|
+
spanOverlapsModifiedRanges
|
|
17
|
+
} from "./chunk-RKBXZN3A.js";
|
|
16
18
|
import {
|
|
17
19
|
stripAnsi
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6HWVI6MI.js";
|
|
19
21
|
import {
|
|
20
22
|
spawnFailedWithNoOutput
|
|
21
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-S67KYG37.js";
|
|
24
|
+
import {
|
|
25
|
+
computeImpactCascade
|
|
26
|
+
} from "./chunk-KN35K52N.js";
|
|
22
27
|
import {
|
|
23
28
|
goClient
|
|
24
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ROYSX2S5.js";
|
|
25
30
|
import {
|
|
26
31
|
isTrivyEnabled,
|
|
27
32
|
resolveSeverityFloor
|
|
28
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-YH5MVY2U.js";
|
|
29
34
|
import {
|
|
30
35
|
rustClient
|
|
31
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-EBC36LNN.js";
|
|
32
37
|
import {
|
|
33
38
|
coveringLaneAvailable,
|
|
34
39
|
createAvailabilityChecker,
|
|
@@ -44,7 +49,7 @@ import {
|
|
|
44
49
|
resolveToolCommand,
|
|
45
50
|
resolveToolCommandWithInstallFallback,
|
|
46
51
|
resolveVendorToolCommand
|
|
47
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-ZHH37KZL.js";
|
|
48
53
|
import {
|
|
49
54
|
biomeConfigArgs,
|
|
50
55
|
findCompiledClassesDir,
|
|
@@ -63,27 +68,24 @@ import {
|
|
|
63
68
|
hasYamllintConfig,
|
|
64
69
|
markdownlintConfigArgs,
|
|
65
70
|
ruffConfigArgs
|
|
66
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-Y6GZHWSJ.js";
|
|
67
72
|
import {
|
|
68
73
|
importFactProvider
|
|
69
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-IYNJ6YPZ.js";
|
|
70
75
|
import {
|
|
71
76
|
functionFactProvider
|
|
72
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-EUXZEFTV.js";
|
|
73
78
|
import {
|
|
74
79
|
extractFactsFromTree
|
|
75
|
-
} from "./chunk-
|
|
76
|
-
import {
|
|
77
|
-
computeImpactCascade
|
|
78
|
-
} from "./chunk-2B73ZPOK.js";
|
|
80
|
+
} from "./chunk-T57LYLZT.js";
|
|
79
81
|
import {
|
|
80
82
|
buildOrUpdateGraph,
|
|
81
83
|
clearReviewGraphWorkspaceCache,
|
|
82
84
|
fileContentProvider
|
|
83
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-XHJBS436.js";
|
|
84
86
|
import {
|
|
85
87
|
MAX_BLOCKING_RULE_COMPLEXITY,
|
|
86
|
-
|
|
88
|
+
PRIMARY_UNAVAILABLE_CAUSE,
|
|
87
89
|
applyDispositions,
|
|
88
90
|
applyDispositionsMultiFile,
|
|
89
91
|
buildEffectiveAstGrepCatalog,
|
|
@@ -92,17 +94,18 @@ import {
|
|
|
92
94
|
classifyDiagnostic,
|
|
93
95
|
classifyDiagnosticTier,
|
|
94
96
|
clearPendingAuxiliaryCoverage,
|
|
97
|
+
combinePrimaryUnavailableCauses,
|
|
95
98
|
enabledAuxiliaryLspServerIds,
|
|
96
|
-
exceedsLspSyncLimits,
|
|
97
99
|
fetchTsserverProjectIdentity,
|
|
98
100
|
getLSPService,
|
|
99
|
-
getRunnerTimeoutFloorMs,
|
|
100
101
|
hasAnyDispositionMarks,
|
|
101
102
|
hasAuxiliaryLspPublishedForRoot,
|
|
102
103
|
hasPendingAuxiliaryCoverage,
|
|
103
104
|
isOverlyBroadPattern,
|
|
104
105
|
isRuleIgnoredForPath,
|
|
105
106
|
isStructuredRule,
|
|
107
|
+
lineContentHash,
|
|
108
|
+
primaryUnavailableCause,
|
|
106
109
|
recordDiagnostics,
|
|
107
110
|
recordNapiFallbackCoverage,
|
|
108
111
|
recordRunner,
|
|
@@ -110,25 +113,40 @@ import {
|
|
|
110
113
|
touchCoverageGap,
|
|
111
114
|
tryWarmAttachedCodeActions,
|
|
112
115
|
tryWarmAttachedDiagnostics
|
|
113
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-RVK72CZX.js";
|
|
117
|
+
import {
|
|
118
|
+
ANY_POSITION,
|
|
119
|
+
retainRecordedFindings
|
|
120
|
+
} from "./chunk-IWDLU6K3.js";
|
|
114
121
|
import {
|
|
115
122
|
mapWithConcurrency
|
|
116
123
|
} from "./chunk-XIMYZ3JA.js";
|
|
117
124
|
import {
|
|
118
125
|
LSP_SERVERS,
|
|
126
|
+
disabledPrimaries,
|
|
119
127
|
getAstGrepRuleSources,
|
|
120
128
|
registerRunnerId,
|
|
121
129
|
resolveAnalysisRoot
|
|
122
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-3DA2JDOL.js";
|
|
123
131
|
import {
|
|
124
132
|
augmentPythonEnvironment,
|
|
125
133
|
detectPythonEnvironment
|
|
126
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-CUHSHSB6.js";
|
|
127
135
|
import {
|
|
128
136
|
loadProjectSnapshot,
|
|
129
137
|
readJsonCache,
|
|
130
138
|
readJsonCacheAsync
|
|
131
|
-
} from "./chunk-
|
|
139
|
+
} from "./chunk-T7FEBKXN.js";
|
|
140
|
+
import {
|
|
141
|
+
RUNTIME_CONFIG,
|
|
142
|
+
exceedsLspSyncLimits,
|
|
143
|
+
getRunnerTimeoutFloorMs,
|
|
144
|
+
loadAstGrepNapi
|
|
145
|
+
} from "./chunk-V35JG4JB.js";
|
|
146
|
+
import {
|
|
147
|
+
buildModuleGraph,
|
|
148
|
+
clearModuleGraphCache
|
|
149
|
+
} from "./chunk-XTBDCR27.js";
|
|
132
150
|
import {
|
|
133
151
|
BUNDLED_QUERIES_ROOT,
|
|
134
152
|
classifyTreeSitterWasmError,
|
|
@@ -148,44 +166,44 @@ import {
|
|
|
148
166
|
ruleFilesForLanguage,
|
|
149
167
|
ruleSourceLanguages,
|
|
150
168
|
walk
|
|
151
|
-
} from "./chunk-
|
|
152
|
-
import {
|
|
153
|
-
buildModuleGraph,
|
|
154
|
-
clearModuleGraphCache
|
|
155
|
-
} from "./chunk-GBPP5P7X.js";
|
|
169
|
+
} from "./chunk-US7ECLD7.js";
|
|
156
170
|
import {
|
|
157
171
|
WORD_INDEX_MAX_BYTES,
|
|
158
172
|
deserializeWordIndex,
|
|
159
173
|
logWordIndex,
|
|
160
174
|
removeWordIndexDocumentAsync,
|
|
161
175
|
scheduleWordIndexPersist,
|
|
176
|
+
setWordIndexPublishedListener,
|
|
162
177
|
updateWordIndexDocumentForEdit
|
|
163
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-W66O5E25.js";
|
|
164
179
|
import {
|
|
165
180
|
PathKeyedMap
|
|
166
181
|
} from "./chunk-Z3CCVDUB.js";
|
|
167
182
|
import {
|
|
168
183
|
WARM_CODE_ACTION_LOOKUP_LIMIT,
|
|
169
|
-
contentHash
|
|
170
|
-
|
|
171
|
-
|
|
184
|
+
contentHash
|
|
185
|
+
} from "./chunk-KAPJINKN.js";
|
|
186
|
+
import {
|
|
187
|
+
resolveRunnerPath,
|
|
188
|
+
toRunnerDisplayPath
|
|
189
|
+
} from "./chunk-AGSS7277.js";
|
|
172
190
|
import {
|
|
173
191
|
isSpawnableCommand
|
|
174
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-GAQ7OQG6.js";
|
|
175
193
|
import {
|
|
176
194
|
logRunnerAdvisoryOnce,
|
|
177
195
|
resolveRunnerCwd,
|
|
178
196
|
resolveRunnerCwdWithReason
|
|
179
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-DEL2U6CM.js";
|
|
180
198
|
import {
|
|
181
199
|
findLocalBinUpwards,
|
|
182
200
|
localBinPath
|
|
183
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-5VSF4UUQ.js";
|
|
184
202
|
import {
|
|
185
203
|
createAvailabilityProbeFlight,
|
|
186
204
|
getIsolatedNpxSpawnOptions,
|
|
187
205
|
probeToolAsync
|
|
188
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-3KAZU3VR.js";
|
|
189
207
|
import {
|
|
190
208
|
classifyProbeFailure,
|
|
191
209
|
createAvailabilityLatch,
|
|
@@ -195,12 +213,12 @@ import {
|
|
|
195
213
|
logAvailabilityDecision,
|
|
196
214
|
startHostStallSampler,
|
|
197
215
|
transientRetryDelayMs
|
|
198
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-P63GXC37.js";
|
|
199
217
|
import {
|
|
200
218
|
getLspCapableKinds,
|
|
201
219
|
getPrimaryDispatchGroup,
|
|
202
220
|
resolveLanguageRootForFile
|
|
203
|
-
} from "./chunk-
|
|
221
|
+
} from "./chunk-HRNHZA3N.js";
|
|
204
222
|
import {
|
|
205
223
|
getGlobalPiLensDir,
|
|
206
224
|
getProjectDataDir,
|
|
@@ -210,25 +228,25 @@ import {
|
|
|
210
228
|
noteSpawnTimeout,
|
|
211
229
|
resolvePiLensFlag,
|
|
212
230
|
safeSpawnAsync
|
|
213
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-KUA4OJ5Y.js";
|
|
214
232
|
import {
|
|
215
233
|
detectFileKind
|
|
216
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-DUO2TU77.js";
|
|
217
235
|
import {
|
|
218
236
|
classifyGeneratedOrArtifactDetailed,
|
|
219
237
|
detectFileRole,
|
|
220
238
|
loadPiLensProjectConfig,
|
|
221
239
|
resolvePiLensConfig
|
|
222
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-J6MPGQTS.js";
|
|
223
241
|
import {
|
|
224
242
|
findNearestDirWithAnyBasename,
|
|
225
243
|
findNearestDirWithMarker,
|
|
226
244
|
getPiLensGlobalConfigPath
|
|
227
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-5HSRT26B.js";
|
|
228
246
|
import {
|
|
229
247
|
getProjectTrustState,
|
|
230
248
|
projectTrustDenialReason
|
|
231
|
-
} from "./chunk-
|
|
249
|
+
} from "./chunk-M2IFVFWU.js";
|
|
232
250
|
import {
|
|
233
251
|
killedForOutputCap,
|
|
234
252
|
truncatedByOutputCap,
|
|
@@ -237,27 +255,28 @@ import {
|
|
|
237
255
|
import {
|
|
238
256
|
incrementDegradationCount,
|
|
239
257
|
recordDegradationOnce
|
|
240
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-J64T55EI.js";
|
|
241
259
|
import {
|
|
242
260
|
createSubsystemLogger,
|
|
243
261
|
logExtension
|
|
244
|
-
} from "./chunk-
|
|
262
|
+
} from "./chunk-POMLXPMY.js";
|
|
245
263
|
import {
|
|
246
264
|
logLatency,
|
|
247
265
|
phaseFinished,
|
|
248
266
|
phaseStarted
|
|
249
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-QBFBRV2B.js";
|
|
250
268
|
import {
|
|
251
269
|
createNdjsonLogger,
|
|
252
270
|
getGlobalPiLensLogDir,
|
|
253
271
|
getMaxLogSizeMB,
|
|
254
272
|
isTestMode
|
|
255
|
-
} from "./chunk-
|
|
273
|
+
} from "./chunk-YNE3RP52.js";
|
|
256
274
|
import {
|
|
257
275
|
FactStore,
|
|
258
276
|
setFactStoreEvictionReporter
|
|
259
|
-
} from "./chunk-
|
|
277
|
+
} from "./chunk-CYRKQRPM.js";
|
|
260
278
|
import {
|
|
279
|
+
BoundedFifoMap,
|
|
261
280
|
BoundedLruCache
|
|
262
281
|
} from "./chunk-ABBOA7UD.js";
|
|
263
282
|
import {
|
|
@@ -270,7 +289,7 @@ import {
|
|
|
270
289
|
normalizeMapKey,
|
|
271
290
|
pathsEqual,
|
|
272
291
|
toProjectRelativePath
|
|
273
|
-
} from "./chunk-
|
|
292
|
+
} from "./chunk-3RKP3FMS.js";
|
|
274
293
|
|
|
275
294
|
// dist/clients/mcp/analyze.js
|
|
276
295
|
import * as fs19 from "node:fs";
|
|
@@ -889,6 +908,62 @@ function createDiagnosticLogger() {
|
|
|
889
908
|
import * as fs3 from "node:fs";
|
|
890
909
|
import * as path4 from "node:path";
|
|
891
910
|
|
|
911
|
+
// dist/clients/line-alignment.js
|
|
912
|
+
var MAX_OWED_LINE_TEXTS = 4096;
|
|
913
|
+
function lineHashOf(line) {
|
|
914
|
+
return Number.parseInt(lineContentHash(line), 16);
|
|
915
|
+
}
|
|
916
|
+
function stampLineHashes(findings, content, isOwn) {
|
|
917
|
+
if (content === void 0)
|
|
918
|
+
return [...findings];
|
|
919
|
+
let lines;
|
|
920
|
+
return findings.map((d) => {
|
|
921
|
+
if (d.lineHash !== void 0 || d.line === void 0 || !isOwn(d))
|
|
922
|
+
return d;
|
|
923
|
+
lines ??= content.split(/\r?\n/);
|
|
924
|
+
const text = lines[d.line - 1];
|
|
925
|
+
return text === void 0 ? d : { ...d, lineHash: lineHashOf(text) };
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
function linesOfRanges(ranges) {
|
|
929
|
+
const lines = [];
|
|
930
|
+
for (const { start, end } of ranges)
|
|
931
|
+
for (let line = start; line <= end; line += 1)
|
|
932
|
+
lines.push(line);
|
|
933
|
+
return lines;
|
|
934
|
+
}
|
|
935
|
+
function rangesOfLines(lines) {
|
|
936
|
+
const sorted = [...new Set(lines)].sort((a, b) => a - b);
|
|
937
|
+
const ranges = [];
|
|
938
|
+
for (const line of sorted) {
|
|
939
|
+
const last = ranges.at(-1);
|
|
940
|
+
if (last && line === last.end + 1)
|
|
941
|
+
last.end = line;
|
|
942
|
+
else
|
|
943
|
+
ranges.push({ start: line, end: line });
|
|
944
|
+
}
|
|
945
|
+
return ranges;
|
|
946
|
+
}
|
|
947
|
+
function owedContentOf(ranges, lineHashes) {
|
|
948
|
+
if (lineHashes === void 0)
|
|
949
|
+
return "whole-file";
|
|
950
|
+
const texts = /* @__PURE__ */ new Set();
|
|
951
|
+
for (const line of linesOfRanges(ranges)) {
|
|
952
|
+
const hash = lineHashes[line - 1];
|
|
953
|
+
if (hash !== void 0)
|
|
954
|
+
texts.add(hash);
|
|
955
|
+
if (texts.size > MAX_OWED_LINE_TEXTS)
|
|
956
|
+
return "whole-file";
|
|
957
|
+
}
|
|
958
|
+
return Uint32Array.from(texts).sort();
|
|
959
|
+
}
|
|
960
|
+
function owedByContentOnly(anchor) {
|
|
961
|
+
const owedContent = new Map(anchor?.owedContent ?? []);
|
|
962
|
+
for (const [runnerId, ranges] of anchor?.owedRanges ?? [])
|
|
963
|
+
owedContent.set(runnerId, owedContentOf(ranges, anchor?.lineHashes));
|
|
964
|
+
return owedContent.size > 0 ? { lineHashes: void 0, owedRanges: /* @__PURE__ */ new Map(), owedContent } : void 0;
|
|
965
|
+
}
|
|
966
|
+
|
|
892
967
|
// dist/clients/dispatch/rule-id-normalize.js
|
|
893
968
|
import * as fs2 from "node:fs";
|
|
894
969
|
import * as path3 from "node:path";
|
|
@@ -1384,8 +1459,8 @@ async function drainPendingRunnerFindings(maxWaitMs = 2e3, currentSession, curre
|
|
|
1384
1459
|
if (maxWaitMs === 0)
|
|
1385
1460
|
await Promise.resolve();
|
|
1386
1461
|
if (maxWaitMs > 0 && current.some((entry) => !entry.settled)) {
|
|
1387
|
-
await new Promise((
|
|
1388
|
-
const timer = setTimeout(
|
|
1462
|
+
await new Promise((resolve45) => {
|
|
1463
|
+
const timer = setTimeout(resolve45, maxWaitMs);
|
|
1389
1464
|
timer.unref?.();
|
|
1390
1465
|
});
|
|
1391
1466
|
}
|
|
@@ -1448,6 +1523,30 @@ function filterGroupsForAdoptedRoot(groups) {
|
|
|
1448
1523
|
return filtered;
|
|
1449
1524
|
}
|
|
1450
1525
|
|
|
1526
|
+
// dist/clients/dispatch/lane-copies.js
|
|
1527
|
+
function semanticRank(semantic) {
|
|
1528
|
+
if (semantic === "blocking")
|
|
1529
|
+
return 4;
|
|
1530
|
+
if (semantic === "warning")
|
|
1531
|
+
return 3;
|
|
1532
|
+
if (semantic === "fixed")
|
|
1533
|
+
return 2;
|
|
1534
|
+
if (semantic === "silent")
|
|
1535
|
+
return 1;
|
|
1536
|
+
return 0;
|
|
1537
|
+
}
|
|
1538
|
+
function laneKey(d) {
|
|
1539
|
+
return `${d.line ?? 1}\0${normalizeRuleId(d.rule ?? "")}`;
|
|
1540
|
+
}
|
|
1541
|
+
function laneCopyStandsFor(lane) {
|
|
1542
|
+
const rankByKey = /* @__PURE__ */ new Map();
|
|
1543
|
+
for (const d of lane) {
|
|
1544
|
+
const key2 = laneKey(d);
|
|
1545
|
+
rankByKey.set(key2, Math.max(rankByKey.get(key2) ?? 0, semanticRank(d.semantic)));
|
|
1546
|
+
}
|
|
1547
|
+
return (d) => (rankByKey.get(laneKey(d)) ?? -1) >= semanticRank(d.semantic);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1451
1550
|
// dist/clients/dispatch/rule-policy.js
|
|
1452
1551
|
function resolvedRulePolicyMap(root) {
|
|
1453
1552
|
const resolved = resolvePiLensConfig({
|
|
@@ -1579,6 +1678,58 @@ function getToolProfile(tool, defectClass) {
|
|
|
1579
1678
|
return TOOL_PROFILE_MAP[t] ?? DEFAULT_TOOL_PROFILE;
|
|
1580
1679
|
}
|
|
1581
1680
|
|
|
1681
|
+
// dist/clients/dispatch/pre-edit-seed.js
|
|
1682
|
+
var PRE_EDIT_SEED_RUNNER_IDS = /* @__PURE__ */ new Set([
|
|
1683
|
+
"actionlint",
|
|
1684
|
+
"biome-check-json",
|
|
1685
|
+
"credo",
|
|
1686
|
+
"detekt",
|
|
1687
|
+
"eslint",
|
|
1688
|
+
"golangci-lint",
|
|
1689
|
+
"hadolint",
|
|
1690
|
+
"htmlhint",
|
|
1691
|
+
"ktlint",
|
|
1692
|
+
"markdownlint",
|
|
1693
|
+
"oxlint",
|
|
1694
|
+
"psscriptanalyzer",
|
|
1695
|
+
"rubocop",
|
|
1696
|
+
"ruff-lint",
|
|
1697
|
+
"rust-clippy",
|
|
1698
|
+
"shellcheck",
|
|
1699
|
+
"spellcheck",
|
|
1700
|
+
"sqlfluff",
|
|
1701
|
+
"stylelint",
|
|
1702
|
+
"swiftlint",
|
|
1703
|
+
"tflint",
|
|
1704
|
+
"vale",
|
|
1705
|
+
"yamllint"
|
|
1706
|
+
]);
|
|
1707
|
+
function preEditSeedFactKey(filePath) {
|
|
1708
|
+
return `session.preEdit.${filePath}`;
|
|
1709
|
+
}
|
|
1710
|
+
function classifyPreExisting(seed, current, content, answered) {
|
|
1711
|
+
let lines;
|
|
1712
|
+
const hashAt = (line) => {
|
|
1713
|
+
if (line === void 0)
|
|
1714
|
+
return void 0;
|
|
1715
|
+
lines ??= content.split(/\r?\n/);
|
|
1716
|
+
const text = lines[line - 1];
|
|
1717
|
+
return text === void 0 ? void 0 : lineHashOf(text);
|
|
1718
|
+
};
|
|
1719
|
+
const candidates = current.filter((d) => d.runnerId !== void 0 && PRE_EDIT_SEED_RUNNER_IDS.has(d.runnerId));
|
|
1720
|
+
const { kept } = retainRecordedFindings(seed, candidates, {
|
|
1721
|
+
positionOf: () => ANY_POSITION,
|
|
1722
|
+
keepUnobserved: (d) => d.runnerId === void 0 || !answered.has(d.runnerId),
|
|
1723
|
+
matchesAnywhere: (prior, observed2) => prior.lineHash !== void 0 && prior.lineHash === hashAt(observed2.line)
|
|
1724
|
+
});
|
|
1725
|
+
const observed = new Set(candidates);
|
|
1726
|
+
const preExisting = kept.filter((d) => observed.has(d));
|
|
1727
|
+
return {
|
|
1728
|
+
preExisting,
|
|
1729
|
+
nextSeed: stampLineHashes(kept, content, (d) => observed.has(d))
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1582
1733
|
// dist/clients/dispatch/utils/format-utils.js
|
|
1583
1734
|
var EMOJI = {
|
|
1584
1735
|
blocking: "\u{1F534}",
|
|
@@ -1833,6 +1984,9 @@ function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedR
|
|
|
1833
1984
|
}
|
|
1834
1985
|
};
|
|
1835
1986
|
}
|
|
1987
|
+
function deltaBaselineFactKey(filePath) {
|
|
1988
|
+
return `session.baseline.${filePath}`;
|
|
1989
|
+
}
|
|
1836
1990
|
function filterDelta(after, before, keyFn) {
|
|
1837
1991
|
const beforeSet = new Set((before ?? []).map(keyFn));
|
|
1838
1992
|
const afterSet = new Set(after.map(keyFn));
|
|
@@ -1840,17 +1994,6 @@ function filterDelta(after, before, keyFn) {
|
|
|
1840
1994
|
const newItems = after.filter((d) => !beforeSet.has(keyFn(d)));
|
|
1841
1995
|
return { new: newItems, fixed };
|
|
1842
1996
|
}
|
|
1843
|
-
function semanticRank(semantic) {
|
|
1844
|
-
if (semantic === "blocking")
|
|
1845
|
-
return 4;
|
|
1846
|
-
if (semantic === "warning")
|
|
1847
|
-
return 3;
|
|
1848
|
-
if (semantic === "fixed")
|
|
1849
|
-
return 2;
|
|
1850
|
-
if (semantic === "silent")
|
|
1851
|
-
return 1;
|
|
1852
|
-
return 0;
|
|
1853
|
-
}
|
|
1854
1997
|
function toolPriority(tool, defectClass) {
|
|
1855
1998
|
return getToolProfile(tool, defectClass).dedupPriority;
|
|
1856
1999
|
}
|
|
@@ -1949,14 +2092,14 @@ function promoteDeltaUnusedToBlockers(diagnostics) {
|
|
|
1949
2092
|
}
|
|
1950
2093
|
function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
1951
2094
|
if (!ctx.kind)
|
|
1952
|
-
return
|
|
2095
|
+
return {};
|
|
1953
2096
|
const lspEnabled = !ctx.pi.getFlag("no-lsp");
|
|
1954
2097
|
const primary2 = getPrimaryDispatchGroup(ctx.kind, lspEnabled);
|
|
1955
2098
|
if (!primary2 || primary2.runnerIds.length === 0)
|
|
1956
|
-
return
|
|
2099
|
+
return {};
|
|
1957
2100
|
const relevant = runnerLatencies.filter((r) => primary2.runnerIds.includes(r.runnerId));
|
|
1958
2101
|
if (relevant.length === 0)
|
|
1959
|
-
return
|
|
2102
|
+
return {};
|
|
1960
2103
|
const unconfirmedServerIds = [
|
|
1961
2104
|
...new Set(relevant.flatMap((r) => r.unconfirmedServerIds ?? []))
|
|
1962
2105
|
];
|
|
@@ -1973,7 +2116,7 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
1973
2116
|
const onceKey2 = `${ctx.kind}:${ctx.filePath}:${dedupeSet(silentServerIds)}|${dedupeSet(deferredServerIds)}`;
|
|
1974
2117
|
if (dedupe) {
|
|
1975
2118
|
if (coverageNoticeSeen.has(onceKey2))
|
|
1976
|
-
return
|
|
2119
|
+
return {};
|
|
1977
2120
|
coverageNoticeSeen.add(onceKey2);
|
|
1978
2121
|
}
|
|
1979
2122
|
const coverageParts = [];
|
|
@@ -1984,20 +2127,22 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
1984
2127
|
coverageParts.push(`coverage: ${markerFor(silentServerIds)} silent \u2014 diagnostics are incomplete (not a clean result).`);
|
|
1985
2128
|
}
|
|
1986
2129
|
return {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2130
|
+
notice: {
|
|
2131
|
+
id: `coverage-partial:${ctx.kind}:${path4.basename(ctx.filePath)}`,
|
|
2132
|
+
message: coverageParts.join("\n"),
|
|
2133
|
+
filePath: ctx.filePath,
|
|
2134
|
+
severity: "warning",
|
|
2135
|
+
semantic: "warning",
|
|
2136
|
+
tool: "pi-lens"
|
|
2137
|
+
}
|
|
1993
2138
|
};
|
|
1994
2139
|
}
|
|
1995
2140
|
const primaryHasCoverage = relevant.some(hasUsableResult);
|
|
1996
2141
|
if (primaryHasCoverage)
|
|
1997
|
-
return
|
|
2142
|
+
return {};
|
|
1998
2143
|
const primaryStillInFlight = relevant.some((r) => r.status === "pending" || r.status === "deferred");
|
|
1999
2144
|
if (primaryStillInFlight)
|
|
2000
|
-
return
|
|
2145
|
+
return {};
|
|
2001
2146
|
const plan = getToolPlan(ctx.kind);
|
|
2002
2147
|
const fallbackRunnerIds = new Set((plan?.groups ?? []).filter((group) => !group.runnerIds.every((runnerId) => primary2.runnerIds.includes(runnerId))).flatMap((group) => group.runnerIds).filter((runnerId) => !primary2.runnerIds.includes(runnerId)));
|
|
2003
2148
|
const STRUCTURAL_RUNNERS = /* @__PURE__ */ new Set([
|
|
@@ -2010,20 +2155,48 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
2010
2155
|
const TYPE_CAPABLE_FALLBACK_RUNNERS = /* @__PURE__ */ new Set(["mypy"]);
|
|
2011
2156
|
const anyFallbackHasCoverage = runnerLatencies.some((r) => fallbackRunnerIds.has(r.runnerId) && !STRUCTURAL_RUNNERS.has(r.runnerId) && hasUsableResult(r) && (!plan?.capabilities.includes("types") || TYPE_CAPABLE_FALLBACK_RUNNERS.has(r.runnerId)));
|
|
2012
2157
|
if (anyFallbackHasCoverage)
|
|
2013
|
-
return
|
|
2158
|
+
return {};
|
|
2159
|
+
const cause = combinePrimaryUnavailableCauses(relevant.flatMap((r) => r.primaryUnavailableCause ?? []));
|
|
2160
|
+
const unconfirmedStatus = cause ? `no language server answered (${PRIMARY_UNAVAILABLE_CAUSE[cause]})` : "not fully checked (a language tool is missing, timed out, or failed to run)";
|
|
2161
|
+
if (cause === "disabled" || cause === "disabledFallback") {
|
|
2162
|
+
const disabledIds = [
|
|
2163
|
+
...new Set(relevant.flatMap((r) => r.disabledPrimaryServerIds ?? []))
|
|
2164
|
+
].sort((a, b) => Number(a > b) - Number(a < b));
|
|
2165
|
+
const onceKeys = disabledIds.map((id) => `disabled-primary:${id}`);
|
|
2166
|
+
if (dedupe) {
|
|
2167
|
+
if (onceKeys.every((key2) => coverageNoticeSeen.has(key2)))
|
|
2168
|
+
return { unconfirmedStatus };
|
|
2169
|
+
for (const key2 of onceKeys)
|
|
2170
|
+
coverageNoticeSeen.add(key2);
|
|
2171
|
+
}
|
|
2172
|
+
return {
|
|
2173
|
+
notice: {
|
|
2174
|
+
id: `coverage-disabled:${ctx.kind}:${disabledIds.join(",")}`,
|
|
2175
|
+
message: cause === "disabled" ? `Pi-lens ${ctx.kind} analysis unconfirmed \u2014 Primary LSP (${disabledIds.join(", ")}) is disabled in config by lsp.disabledServers, so no language server checks these files this session (not a clean result).` : `Pi-lens ${ctx.kind} analysis unconfirmed \u2014 Primary LSP (${disabledIds.join(", ")}) is disabled in config by lsp.disabledServers and its fallback did not answer, so no language server checked these files (not a clean result).`,
|
|
2176
|
+
filePath: ctx.filePath,
|
|
2177
|
+
severity: "warning",
|
|
2178
|
+
semantic: "warning",
|
|
2179
|
+
tool: "pi-lens"
|
|
2180
|
+
},
|
|
2181
|
+
unconfirmedStatus
|
|
2182
|
+
};
|
|
2183
|
+
}
|
|
2014
2184
|
const onceKey = `${ctx.kind}:${ctx.filePath}`;
|
|
2015
2185
|
if (dedupe) {
|
|
2016
2186
|
if (coverageNoticeSeen.has(onceKey))
|
|
2017
|
-
return
|
|
2187
|
+
return { unconfirmedStatus };
|
|
2018
2188
|
coverageNoticeSeen.add(onceKey);
|
|
2019
2189
|
}
|
|
2020
2190
|
return {
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2191
|
+
notice: {
|
|
2192
|
+
id: `coverage-unavailable:${ctx.kind}:${path4.basename(ctx.filePath)}`,
|
|
2193
|
+
message: `Pi-lens ${ctx.kind} analysis unavailable \u2014 a language tool is missing, timed out, or failed to run, or the LSP server isn't ready yet, so this file was not fully checked (not a clean result).`,
|
|
2194
|
+
filePath: ctx.filePath,
|
|
2195
|
+
severity: "warning",
|
|
2196
|
+
semantic: "warning",
|
|
2197
|
+
tool: "pi-lens"
|
|
2198
|
+
},
|
|
2199
|
+
unconfirmedStatus
|
|
2027
2200
|
};
|
|
2028
2201
|
}
|
|
2029
2202
|
var latencyReports = [];
|
|
@@ -2036,10 +2209,29 @@ function clearCoverageNoticeState() {
|
|
|
2036
2209
|
coverageNoticeSeen.clear();
|
|
2037
2210
|
generatedSkipRecorded.clear();
|
|
2038
2211
|
}
|
|
2212
|
+
function runnerDispatchContext(ctx, runnerId) {
|
|
2213
|
+
const owed = ctx.owedRanges?.get(runnerId);
|
|
2214
|
+
if (!owed?.length || !ctx.modifiedRanges)
|
|
2215
|
+
return ctx;
|
|
2216
|
+
return {
|
|
2217
|
+
...ctx,
|
|
2218
|
+
modifiedRanges: rangesOfLines([
|
|
2219
|
+
...linesOfRanges(ctx.modifiedRanges),
|
|
2220
|
+
...linesOfRanges(owed)
|
|
2221
|
+
])
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2039
2224
|
async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
2040
2225
|
const diagnostics = [];
|
|
2041
2226
|
const latencies = [];
|
|
2042
2227
|
let hadBlocker = false;
|
|
2228
|
+
const outOfEditScope = [];
|
|
2229
|
+
const inconclusiveRunnerIds = [];
|
|
2230
|
+
const inconclusiveServerIds = [];
|
|
2231
|
+
const collectLaterRunnerIds = [];
|
|
2232
|
+
const editScopedRunnerIds = [];
|
|
2233
|
+
const answeredRunnerIds = [];
|
|
2234
|
+
const coveredRunners = [];
|
|
2043
2235
|
const runnerIds = group.filterKinds ? group.runnerIds.filter((id) => {
|
|
2044
2236
|
const runner = registry.get(id);
|
|
2045
2237
|
return runner && ctx.kind && group.filterKinds?.includes(ctx.kind);
|
|
@@ -2121,6 +2313,7 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2121
2313
|
} catch (error) {
|
|
2122
2314
|
ctx.log(`Runner ${runner.id} precondition failed: ${error}`);
|
|
2123
2315
|
shouldRun = false;
|
|
2316
|
+
inconclusiveRunnerIds.push(runner.id);
|
|
2124
2317
|
}
|
|
2125
2318
|
}
|
|
2126
2319
|
if (!shouldRun) {
|
|
@@ -2145,10 +2338,11 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2145
2338
|
continue;
|
|
2146
2339
|
}
|
|
2147
2340
|
const projectRoot = ctx.projectRoot ?? ctx.cwd;
|
|
2341
|
+
const runnerCtx = runnerDispatchContext(ctx, runner.id);
|
|
2148
2342
|
const observedTier = ctx.writeIndex === void 0 ? "inline" : classifyObservedRunner(projectRoot, runner.id);
|
|
2149
2343
|
if (observedTier === "collect-later") {
|
|
2150
2344
|
const markedAtMs = Date.now();
|
|
2151
|
-
const deferred = runRunner(
|
|
2345
|
+
const deferred = runRunner(runnerCtx, runner, semantic).then((result2) => {
|
|
2152
2346
|
const durationMs = Date.now() - markedAtMs;
|
|
2153
2347
|
const tier2 = observeRunnerLatency({
|
|
2154
2348
|
projectRoot,
|
|
@@ -2215,6 +2409,8 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2215
2409
|
semantic
|
|
2216
2410
|
});
|
|
2217
2411
|
recordRunner(ctx.filePath, runner.id, "pending", 0, 0, ctx.writeIndex);
|
|
2412
|
+
inconclusiveRunnerIds.push(runner.id);
|
|
2413
|
+
collectLaterRunnerIds.push(runner.id);
|
|
2218
2414
|
logLatency({
|
|
2219
2415
|
type: "runner",
|
|
2220
2416
|
filePath: ctx.filePath,
|
|
@@ -2227,7 +2423,7 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2227
2423
|
});
|
|
2228
2424
|
continue;
|
|
2229
2425
|
}
|
|
2230
|
-
const result = await runRunner(
|
|
2426
|
+
const result = await runRunner(runnerCtx, runner, semantic);
|
|
2231
2427
|
onRunnerResult?.(runnerId, result);
|
|
2232
2428
|
const runnerEnd = Date.now();
|
|
2233
2429
|
const duration = runnerEnd - runnerStart;
|
|
@@ -2282,6 +2478,12 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2282
2478
|
},
|
|
2283
2479
|
...result.deferredServerIds !== void 0 && {
|
|
2284
2480
|
deferredServerIds: result.deferredServerIds
|
|
2481
|
+
},
|
|
2482
|
+
...result.primaryUnavailableCause !== void 0 && {
|
|
2483
|
+
primaryUnavailableCause: result.primaryUnavailableCause
|
|
2484
|
+
},
|
|
2485
|
+
...result.disabledPrimaryServerIds !== void 0 && {
|
|
2486
|
+
disabledPrimaryServerIds: result.disabledPrimaryServerIds
|
|
2285
2487
|
}
|
|
2286
2488
|
});
|
|
2287
2489
|
logLatency({
|
|
@@ -2301,7 +2503,28 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2301
2503
|
})) : void 0,
|
|
2302
2504
|
metadata: failureRowMetadata(result) ?? (skipReason ? { skipReason, ...claimSource !== void 0 && { claimSource } } : void 0)
|
|
2303
2505
|
});
|
|
2304
|
-
|
|
2506
|
+
if (!ctx.preEditCapture)
|
|
2507
|
+
recordRunner(ctx.filePath, runnerId, result.status, result.diagnostics.length, duration, ctx.writeIndex);
|
|
2508
|
+
for (const d of result.diagnostics)
|
|
2509
|
+
d.runnerId ??= runnerId;
|
|
2510
|
+
for (const d of result.outOfEditScope ?? []) {
|
|
2511
|
+
d.runnerId ??= runnerId;
|
|
2512
|
+
outOfEditScope.push(d);
|
|
2513
|
+
}
|
|
2514
|
+
if (reachedNoVerdict(result))
|
|
2515
|
+
inconclusiveRunnerIds.push(runnerId);
|
|
2516
|
+
else {
|
|
2517
|
+
answeredRunnerIds.push(runnerId);
|
|
2518
|
+
if (result.coveredBy)
|
|
2519
|
+
coveredRunners.push({
|
|
2520
|
+
runnerId,
|
|
2521
|
+
lane: result.coveredBy,
|
|
2522
|
+
ran: result.skipReason !== "covered-by-primary"
|
|
2523
|
+
});
|
|
2524
|
+
if (result.editScopedVerdict === true)
|
|
2525
|
+
editScopedRunnerIds.push(runnerId);
|
|
2526
|
+
}
|
|
2527
|
+
inconclusiveServerIds.push(...result.unconfirmedServerIds ?? [], ...result.deferredServerIds ?? []);
|
|
2305
2528
|
diagnostics.push(...result.diagnostics);
|
|
2306
2529
|
const resultSemantic = result.semantic ?? semantic;
|
|
2307
2530
|
if (resultSemantic === "blocking" && result.diagnostics.length > 0 || result.diagnostics.some((d) => d.semantic === "blocking")) {
|
|
@@ -2311,7 +2534,18 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2311
2534
|
break;
|
|
2312
2535
|
}
|
|
2313
2536
|
}
|
|
2314
|
-
return {
|
|
2537
|
+
return {
|
|
2538
|
+
diagnostics,
|
|
2539
|
+
latencies,
|
|
2540
|
+
hadBlocker,
|
|
2541
|
+
outOfEditScope,
|
|
2542
|
+
inconclusiveRunnerIds,
|
|
2543
|
+
inconclusiveServerIds,
|
|
2544
|
+
collectLaterRunnerIds,
|
|
2545
|
+
editScopedRunnerIds,
|
|
2546
|
+
answeredRunnerIds,
|
|
2547
|
+
coveredRunners
|
|
2548
|
+
};
|
|
2315
2549
|
}
|
|
2316
2550
|
async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
2317
2551
|
const _overallStart = Date.now();
|
|
@@ -2385,7 +2619,8 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2385
2619
|
metadata: {
|
|
2386
2620
|
groupCount: groups.length,
|
|
2387
2621
|
kind: ctx.kind,
|
|
2388
|
-
runners: allRunnerIds.join(",")
|
|
2622
|
+
runners: allRunnerIds.join(","),
|
|
2623
|
+
...ctx.preEditCapture && { preEditCapture: true }
|
|
2389
2624
|
}
|
|
2390
2625
|
});
|
|
2391
2626
|
const groupResults = await Promise.all(groups.map((group) => runGroup(ctx, group, registry, onRunnerResult)));
|
|
@@ -2397,17 +2632,51 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2397
2632
|
reason: "dispatchForFile requires an absolute ctx.filePath to key the delta baseline (refs #2489)"
|
|
2398
2633
|
});
|
|
2399
2634
|
}
|
|
2400
|
-
const baselineAbsKey =
|
|
2635
|
+
const baselineAbsKey = deltaBaselineFactKey(ctx.filePath);
|
|
2401
2636
|
const previousBaseline = ctx.deltaMode && baselinePathSafe ? ctx.facts.getBoundedSessionFact(baselineAbsKey) : void 0;
|
|
2402
2637
|
const baselineWarnings = previousBaseline?.filter((d) => d.semantic === "warning" || d.semantic === "none");
|
|
2403
2638
|
const baselineWarningCount = baselineWarnings?.length ?? 0;
|
|
2404
|
-
|
|
2639
|
+
const outOfEditScope = [];
|
|
2640
|
+
const inconclusiveRunnerIds = /* @__PURE__ */ new Set();
|
|
2641
|
+
const inconclusiveServerIds = /* @__PURE__ */ new Set();
|
|
2642
|
+
const collectLaterRunnerIds = /* @__PURE__ */ new Set();
|
|
2643
|
+
const editScopedRunnerIds = [];
|
|
2644
|
+
const answeredRunnerIds = /* @__PURE__ */ new Set();
|
|
2645
|
+
const coveredRunners = [];
|
|
2646
|
+
for (const { diagnostics: groupDiags, latencies, hadBlocker, outOfEditScope: groupOutOfScope, inconclusiveRunnerIds: groupRunnerIds, inconclusiveServerIds: groupServerIds, collectLaterRunnerIds: groupCollectLater, editScopedRunnerIds: groupEditScoped, answeredRunnerIds: groupAnswered, coveredRunners: groupCovered } of groupResults) {
|
|
2405
2647
|
runnerLatencies.push(...latencies);
|
|
2648
|
+
outOfEditScope.push(...groupOutOfScope);
|
|
2649
|
+
for (const id of groupRunnerIds)
|
|
2650
|
+
inconclusiveRunnerIds.add(id);
|
|
2651
|
+
for (const id of groupServerIds)
|
|
2652
|
+
inconclusiveServerIds.add(id);
|
|
2653
|
+
for (const id of groupCollectLater)
|
|
2654
|
+
collectLaterRunnerIds.add(id);
|
|
2655
|
+
editScopedRunnerIds.push(...groupEditScoped);
|
|
2656
|
+
for (const id of groupAnswered)
|
|
2657
|
+
answeredRunnerIds.add(id);
|
|
2658
|
+
coveredRunners.push(...groupCovered);
|
|
2406
2659
|
allDiagnostics.push(...groupDiags);
|
|
2407
2660
|
if (hadBlocker)
|
|
2408
2661
|
stopped = true;
|
|
2409
2662
|
}
|
|
2410
|
-
const
|
|
2663
|
+
const voidedCovers = /* @__PURE__ */ new Set();
|
|
2664
|
+
const laneCopyByRunner = /* @__PURE__ */ new Map();
|
|
2665
|
+
for (const { runnerId, lane, ran } of coveredRunners) {
|
|
2666
|
+
const silent = !answeredRunnerIds.has(lane.runnerId) || lane.serverId !== void 0 && inconclusiveServerIds.has(lane.serverId);
|
|
2667
|
+
if (ran) {
|
|
2668
|
+
if (silent)
|
|
2669
|
+
continue;
|
|
2670
|
+
laneCopyByRunner.set(runnerId, laneCopyStandsFor(allDiagnostics.flatMap((d) => d.runnerId === lane.runnerId && (lane.serverId === void 0 || d.serverId === lane.serverId) ? [d] : [])));
|
|
2671
|
+
continue;
|
|
2672
|
+
}
|
|
2673
|
+
if (!silent)
|
|
2674
|
+
continue;
|
|
2675
|
+
voidedCovers.add(runnerId);
|
|
2676
|
+
inconclusiveRunnerIds.add(runnerId);
|
|
2677
|
+
}
|
|
2678
|
+
const deliveredDiagnostics = laneCopyByRunner.size === 0 ? allDiagnostics : allDiagnostics.flatMap((d) => laneCopyByRunner.get(d.runnerId ?? "")?.(d) ? [] : [d]);
|
|
2679
|
+
const dedupedDiagnostics = dedupeOverlappingDiagnostics(deliveredDiagnostics);
|
|
2411
2680
|
const fileContent = ctx.facts.getFileFact(ctx.filePath, "file.content") ?? "";
|
|
2412
2681
|
const rulePolicy = ctx.rulePolicy ?? rulePolicyMapFromConfig(loadPiLensProjectConfig(ctx.projectRoot ?? ctx.cwd).rules);
|
|
2413
2682
|
const applyOutputFilters = (diags) => {
|
|
@@ -2422,11 +2691,33 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2422
2691
|
};
|
|
2423
2692
|
let visibleDiagnostics = applyOutputFilters(dedupedDiagnostics);
|
|
2424
2693
|
let resolvedCount = 0;
|
|
2694
|
+
const stillObserved = outOfEditScope.length > 0 ? applyOutputFilters(outOfEditScope).flatMap((d) => d.semantic === "blocking" ? [d] : []) : [];
|
|
2695
|
+
let heldBackBlockers = [];
|
|
2425
2696
|
if (ctx.deltaMode && previousBaseline) {
|
|
2426
2697
|
const filtered = filterDelta(visibleDiagnostics, applyOutputFilters(previousBaseline), (d) => d.id);
|
|
2698
|
+
const isNew = new Set(filtered.new);
|
|
2699
|
+
heldBackBlockers = visibleDiagnostics.filter((d) => d.semantic === "blocking" && !isNew.has(d));
|
|
2700
|
+
stillObserved.push(...promoteDeltaUnusedToBlockers(visibleDiagnostics.flatMap((d) => !isNew.has(d) && d.semantic !== "blocking" && isUnusedValueDiagnostic(d) ? [d] : [])));
|
|
2427
2701
|
visibleDiagnostics = promoteDeltaUnusedToBlockers(filtered.new);
|
|
2428
2702
|
resolvedCount = filtered.fixed.length;
|
|
2429
2703
|
}
|
|
2704
|
+
const seedKey = preEditSeedFactKey(ctx.filePath);
|
|
2705
|
+
const preEditSeed = ctx.deltaMode && baselinePathSafe ? ctx.facts.getBoundedSessionFact(seedKey) : void 0;
|
|
2706
|
+
const seedContent = ctx.facts.getFileFact(ctx.filePath, "file.content");
|
|
2707
|
+
let preExisting = [];
|
|
2708
|
+
if (preEditSeed && seedContent !== void 0) {
|
|
2709
|
+
const classified = classifyPreExisting(preEditSeed, [
|
|
2710
|
+
...visibleDiagnostics.filter((d) => d.semantic === "blocking"),
|
|
2711
|
+
...heldBackBlockers
|
|
2712
|
+
], seedContent, new Set([...answeredRunnerIds].filter((id) => !inconclusiveRunnerIds.has(id))));
|
|
2713
|
+
if (classified.preExisting.length > 0) {
|
|
2714
|
+
const held = new Set(classified.preExisting);
|
|
2715
|
+
visibleDiagnostics = visibleDiagnostics.filter((d) => !held.has(d));
|
|
2716
|
+
heldBackBlockers = heldBackBlockers.filter((d) => !held.has(d));
|
|
2717
|
+
preExisting = classified.preExisting;
|
|
2718
|
+
}
|
|
2719
|
+
ctx.facts.setBoundedSessionFact(seedKey, classified.nextSeed);
|
|
2720
|
+
}
|
|
2430
2721
|
if (ctx.deltaMode && baselinePathSafe) {
|
|
2431
2722
|
ctx.facts.setBoundedSessionFact(baselineAbsKey, [...dedupedDiagnostics]);
|
|
2432
2723
|
}
|
|
@@ -2438,21 +2729,21 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2438
2729
|
provider: ctx.telemetryProvider
|
|
2439
2730
|
};
|
|
2440
2731
|
if (fixedItems.length > 0) {
|
|
2441
|
-
import("./chunk-
|
|
2732
|
+
import("./chunk-JUKMK5Y4.js").then(({ appendToWorklog }) => {
|
|
2442
2733
|
appendToWorklog(ctx.cwd, fixedItems, true, worklogIdentity);
|
|
2443
2734
|
}).catch(() => {
|
|
2444
2735
|
});
|
|
2445
2736
|
}
|
|
2446
2737
|
const fixableWarnings = warnings.filter((d) => d.fixable);
|
|
2447
2738
|
if (fixableWarnings.length > 0) {
|
|
2448
|
-
import("./chunk-
|
|
2739
|
+
import("./chunk-JUKMK5Y4.js").then(({ appendToWorklog }) => {
|
|
2449
2740
|
appendToWorklog(ctx.cwd, fixableWarnings, false, worklogIdentity);
|
|
2450
2741
|
}).catch(() => {
|
|
2451
2742
|
});
|
|
2452
2743
|
}
|
|
2453
2744
|
const inlineBlockers = blockers;
|
|
2454
2745
|
const inlineFixed = fixedItems;
|
|
2455
|
-
const coverageNotice = buildCoverageNotice(ctx, runnerLatencies, options?.dedupeCoverageNotice ?? true);
|
|
2746
|
+
const { notice: coverageNotice, unconfirmedStatus } = buildCoverageNotice(ctx, runnerLatencies, options?.dedupeCoverageNotice ?? true);
|
|
2456
2747
|
const blockerOutput = formatDiagnostics(inlineBlockers, "blocking");
|
|
2457
2748
|
let output = blockerOutput;
|
|
2458
2749
|
output += formatDiagnostics(inlineFixed, "fixed");
|
|
@@ -2508,7 +2799,19 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2508
2799
|
// (above, `metadata: { groupCount, kind, runners }`) fires before the
|
|
2509
2800
|
// baseline read ever runs and cannot carry either value.
|
|
2510
2801
|
baselineHit: previousBaseline !== void 0,
|
|
2511
|
-
baselineWarningCount
|
|
2802
|
+
baselineWarningCount,
|
|
2803
|
+
// #4484: blockers still observed that the delta did not call new.
|
|
2804
|
+
heldBackBlockers: heldBackBlockers.length,
|
|
2805
|
+
// #4483: whether a pre-edit seed was read, and the blocking linter
|
|
2806
|
+
// findings it reported as pre-existing.
|
|
2807
|
+
preEditSeed: preEditSeed !== void 0,
|
|
2808
|
+
preExisting: preExisting.length,
|
|
2809
|
+
...ctx.preEditCapture && { preEditCapture: true },
|
|
2810
|
+
// #4484 r2: findings that only keep a recorded blocker pending, and
|
|
2811
|
+
// the sources whose silence is no evidence.
|
|
2812
|
+
stillObserved: stillObserved.length,
|
|
2813
|
+
inconclusiveRunners: inconclusiveRunnerIds.size,
|
|
2814
|
+
inconclusiveServers: inconclusiveServerIds.size
|
|
2512
2815
|
}
|
|
2513
2816
|
});
|
|
2514
2817
|
return {
|
|
@@ -2521,7 +2824,21 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2521
2824
|
resolvedCount,
|
|
2522
2825
|
output,
|
|
2523
2826
|
blockerOutput,
|
|
2524
|
-
hasBlockers: blockers.length > 0
|
|
2827
|
+
hasBlockers: blockers.length > 0,
|
|
2828
|
+
...heldBackBlockers.length > 0 && { heldBackBlockers },
|
|
2829
|
+
...preExisting.length > 0 && { preExisting },
|
|
2830
|
+
...stillObserved.length > 0 && { stillObserved },
|
|
2831
|
+
...editScopedRunnerIds.some((id) => !voidedCovers.has(id)) && {
|
|
2832
|
+
editScopedRunnerIds: editScopedRunnerIds.flatMap((id) => voidedCovers.has(id) ? [] : [id])
|
|
2833
|
+
},
|
|
2834
|
+
...(inconclusiveRunnerIds.size > 0 || inconclusiveServerIds.size > 0) && {
|
|
2835
|
+
inconclusiveSources: {
|
|
2836
|
+
runnerIds: [...inconclusiveRunnerIds],
|
|
2837
|
+
serverIds: [...inconclusiveServerIds],
|
|
2838
|
+
collectLaterRunnerIds: [...collectLaterRunnerIds]
|
|
2839
|
+
}
|
|
2840
|
+
},
|
|
2841
|
+
...unconfirmedStatus !== void 0 && { unconfirmedStatus }
|
|
2525
2842
|
};
|
|
2526
2843
|
}
|
|
2527
2844
|
var RUNNER_TIMEOUT_MS = RUNTIME_CONFIG.dispatch.runnerTimeoutMs;
|
|
@@ -2602,6 +2919,16 @@ var DEFAULT_NEIGHBOUR_BUDGET = 40;
|
|
|
2602
2919
|
var CASCADE_NEIGHBOUR_BUDGET = Math.max(MIN_NEIGHBOUR_BUDGET, Number.parseInt(process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET ?? "40", 10) || DEFAULT_NEIGHBOUR_BUDGET);
|
|
2603
2920
|
var NEIGHBOUR_BUDGET_OVERRIDDEN = process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET !== void 0 && CASCADE_NEIGHBOUR_BUDGET !== DEFAULT_NEIGHBOUR_BUDGET;
|
|
2604
2921
|
|
|
2922
|
+
// dist/clients/dispatch/runners/utils.js
|
|
2923
|
+
import * as fs4 from "node:fs";
|
|
2924
|
+
function readFileContent(filePath) {
|
|
2925
|
+
try {
|
|
2926
|
+
return fs4.readFileSync(filePath, "utf-8");
|
|
2927
|
+
} catch {
|
|
2928
|
+
return void 0;
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2605
2932
|
// dist/clients/dispatch/utils/lsp-diagnostics.js
|
|
2606
2933
|
function convertLspDiagnostics(diags, filePath, options = {}) {
|
|
2607
2934
|
const tool = options.tool ?? "lsp";
|
|
@@ -2630,7 +2957,10 @@ function convertLspDiagnostics(diags, filePath, options = {}) {
|
|
|
2630
2957
|
autoFixAvailable: false,
|
|
2631
2958
|
fixKind: hasSuggestion ? "suggestion" : void 0,
|
|
2632
2959
|
fixSuggestion: options.fixSuggestionByIndex?.get(idx),
|
|
2633
|
-
scanOrigin: options.scanOrigin
|
|
2960
|
+
scanOrigin: options.scanOrigin,
|
|
2961
|
+
// #4484 r2: the publishing server, so a run that leaves it
|
|
2962
|
+
// unconfirmed keeps its recorded blockers. Never identity.
|
|
2963
|
+
...d.serverId !== void 0 && { serverId: d.serverId }
|
|
2634
2964
|
};
|
|
2635
2965
|
});
|
|
2636
2966
|
}
|
|
@@ -2644,7 +2974,8 @@ function applyFindingPolicy(diagnostics, options) {
|
|
|
2644
2974
|
root: options.cwd,
|
|
2645
2975
|
filePath: options.filePath
|
|
2646
2976
|
}),
|
|
2647
|
-
inlineKept
|
|
2977
|
+
inlineKept,
|
|
2978
|
+
disposed
|
|
2648
2979
|
};
|
|
2649
2980
|
}
|
|
2650
2981
|
function loadProjectRulePolicyMap(cwd) {
|
|
@@ -2709,6 +3040,28 @@ function applyPushedFindingPolicy(findings, options) {
|
|
|
2709
3040
|
});
|
|
2710
3041
|
return { kept, suppressed: findings.length - kept.length };
|
|
2711
3042
|
}
|
|
3043
|
+
function applyPushedFindingPolicyByFile(findings, cwd) {
|
|
3044
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
3045
|
+
for (const finding of findings) {
|
|
3046
|
+
const group = byFile.get(finding.filePath);
|
|
3047
|
+
if (group)
|
|
3048
|
+
group.push(finding);
|
|
3049
|
+
else
|
|
3050
|
+
byFile.set(finding.filePath, [finding]);
|
|
3051
|
+
}
|
|
3052
|
+
const kept = [];
|
|
3053
|
+
let suppressed = 0;
|
|
3054
|
+
for (const [filePath, group] of byFile) {
|
|
3055
|
+
const policy = applyPushedFindingPolicy(group, {
|
|
3056
|
+
cwd,
|
|
3057
|
+
filePath,
|
|
3058
|
+
content: readFileContent(filePath)
|
|
3059
|
+
});
|
|
3060
|
+
kept.push(...policy.kept);
|
|
3061
|
+
suppressed += policy.suppressed;
|
|
3062
|
+
}
|
|
3063
|
+
return { kept, suppressed };
|
|
3064
|
+
}
|
|
2712
3065
|
function expandRenderedIdentities(rendered) {
|
|
2713
3066
|
const out = [];
|
|
2714
3067
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2819,6 +3172,12 @@ function formatCacheAgeLabel(scannedAt, nowMs = Date.now()) {
|
|
|
2819
3172
|
const remMinutes = ageMinutes % 60;
|
|
2820
3173
|
return remMinutes === 0 ? `scanned ${ageHours}h ago` : `scanned ${ageHours}h ${remMinutes}m ago`;
|
|
2821
3174
|
}
|
|
3175
|
+
function dispositionSuppressedLine(suppressed, breakdown) {
|
|
3176
|
+
if (suppressed <= 0)
|
|
3177
|
+
return void 0;
|
|
3178
|
+
const lanes = breakdown ? ` (${breakdown})` : "";
|
|
3179
|
+
return `suppressed by disposition: ${suppressed} finding(s)${lanes} dropped from this result because they're marked false-positive/won't-fix, disabled by \`.pi-lens.json\` rule policy, or suppressed by an inline \`pi-lens-ignore\` comment. Not a clean verdict for those locations \u2014 they were found, then intentionally hidden.`;
|
|
3180
|
+
}
|
|
2822
3181
|
function admitsProjectWideFindings(sessionRole) {
|
|
2823
3182
|
return sessionRole === "primary";
|
|
2824
3183
|
}
|
|
@@ -2932,6 +3291,17 @@ var DELIVERY_SURFACES = {
|
|
|
2932
3291
|
{ evidenceMin: 2 }
|
|
2933
3292
|
),
|
|
2934
3293
|
"runtime-turn:cascade-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F9EA} cascade neighbor blocker.", "Cascade results settle synchronously this turn where possible (`settleCascadeRuns`), but an unsettled compute can carry over to a later turn (bounded by a carry cap) \u2014 a carried-over result renders with an explicit `(carried N turns \xB7 scanned Xm ago)` label (#3167, #3168 F3), so the agent can tell it from a fresh observation.", "live", ["cascadeCarrySuffix("], { evidenceMin: 1 }),
|
|
3294
|
+
// #4487: cascade neighbour errors a cascade showed in an EARLIER turn and
|
|
3295
|
+
// no later cascade or edit has shown gone. A cached claim, not a fresh
|
|
3296
|
+
// observation, so each entry passes the freshness gate against its own
|
|
3297
|
+
// read bound (`checkedAt`) before it renders (#4495 review F1, round 3):
|
|
3298
|
+
// a deleted neighbour is forgotten; one written after the check by
|
|
3299
|
+
// something pi never saw is named once as changed and not re-checked.
|
|
3300
|
+
// Survivors carry the `(scanned Xm ago)` age of that read. The evidence is
|
|
3301
|
+
// the two RENDERED lists, so the binding chain walks each back to the gate
|
|
3302
|
+
// call's own arms (a render of the ungated candidates reds, #4495 r2
|
|
3303
|
+
// verify census note).
|
|
3304
|
+
"runtime-turn:cascade-pending-errors": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F4D0} list of cascade neighbour errors shown in an earlier turn and not re-checked since.", ["gateFindingsByPathFreshness"], ["unresolvedNeighbors", "changedShown"]),
|
|
2935
3305
|
"runtime-turn:cascade-coverage-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end cascade-coverage-gap advisories (graph/binding/budget).", "Explains what the cascade check could NOT confirm this turn \u2014 not a finding with a cited path, an absence-of-coverage disclosure computed from this turn's own indeterminate-run list. An advisory computed from a carried indeterminate run is labeled `(carried N turns \xB7 <age>)` (#3167, #3168 F4 \u2014 dropped on mixed carried/fresh buckets). The age half reads `scan age unknown` on this surface today: no indeterminate-run producer stamps `observedAt` (only the resolved-found plumb does, `clients/cascade-format.ts`), and one unstamped carried run collapses the whole bucket's age rather than claiming the stamped runs' (#3168 F13). The carry COUNT is always real.", "live", ["withCarryLabel("], { evidenceMin: 3 }),
|
|
2936
3306
|
// #3102: the cold-neighbour cascade run is BUILT here, in the quiet-window
|
|
2937
3307
|
// reconcile (`onResolvedFound` in index.ts), a turn earlier than the
|
|
@@ -3020,16 +3390,185 @@ var DELIVERY_SURFACES = {
|
|
|
3020
3390
|
"read-guard-tool-lines:preflight-errors": labeled("clients/read-guard-tool-lines.ts", "Read-guard hashline BLOCKED / RE-READ REQUIRED / PARTIAL APPLY / ALREADY APPLIED preflight errors (#2402).", "Computed fresh per edit attempt and returned as that attempt's rejection \u2014 no cached findings are replayed, so there is no staleness window. The PARTIAL APPLY and ALREADY APPLIED variants describe the same attempt's commit outcome; applied-edit recognition reads RuntimeCoordinator's session-scoped record, which resets with the session.", "live"),
|
|
3021
3391
|
"mutating-tool:adapter-preflight-errors": labeled("clients/mutating-tool.ts", "Shape-adapter BLOCKED preflight errors for hashline edit inputs the adapter recognized but could not resolve to a range (#2423).", "Computed fresh from the tool input on each attempt and returned as that attempt's rejection, so there is no staleness window. The adapters read only the call's own arguments; nothing cached is replayed.", "live"),
|
|
3022
3392
|
"tool-call:duplicate-export-blocker": labeled("clients/runtime-tool-call.ts", "Duplicate-export STOP rejection returned inline with the failed edit.", "Synchronous preflight rejection computed per edit attempt; no stored state.", "live"),
|
|
3023
|
-
"agent-behavior:thrashing-notice": labeled("clients/agent-behavior-client.ts", "In-result thrashing/blind-write detection notice.", "Ephemeral notice computed at detection time inside the same tool result \u2014 no persistence and no cache, so nothing can be stale.", "live")
|
|
3393
|
+
"agent-behavior:thrashing-notice": labeled("clients/agent-behavior-client.ts", "In-result thrashing/blind-write detection notice.", "Ephemeral notice computed at detection time inside the same tool result \u2014 no persistence and no cache, so nothing can be stale.", "live"),
|
|
3394
|
+
// ── #1634 enumeration round: the rest of the agent-facing sinks ─────────
|
|
3395
|
+
// Found by the sink census in `tests/clients/finding-delivery-gate.test.ts`,
|
|
3396
|
+
// which derives every production file holding an agent-facing sink (a tool
|
|
3397
|
+
// result's text block, a context or hook message, a tool_call block, a
|
|
3398
|
+
// custom entry, a status/widget line) and fails on one that is neither a
|
|
3399
|
+
// surface `file` here nor classified there.
|
|
3400
|
+
"lsp-navigation:workspace-diagnostics-path": gated(
|
|
3401
|
+
"tools/lsp-navigation.ts",
|
|
3402
|
+
"`lsp_navigation workspaceDiagnostics` with a path: the server's answer for that file, read after a touch that waits for diagnostics.",
|
|
3403
|
+
["applyProbeFindingPolicy"],
|
|
3404
|
+
// The path read and the tracked snapshot below are the two calls.
|
|
3405
|
+
["applyProbeFindingPolicy("],
|
|
3406
|
+
{ evidenceMin: 2 }
|
|
3407
|
+
),
|
|
3408
|
+
"lsp-navigation:tracked-snapshot": labeled("tools/lsp-navigation.ts", "`lsp_navigation workspaceDiagnostics` with no path: each tracked file's last client publish.", "A replay of what each language client last published, with no re-check of the file, so every row states its age. The rows also pass the same finding policy as the path read (`readFileContent` supplies the current content), so the label and the disposition filter compose.", "LSP client publish ts", ["lag: formatCacheAgeLabel(ts)", "readFileContent(trackedFile)"]),
|
|
3409
|
+
"runtime-context:persisted-findings": gated(
|
|
3410
|
+
"clients/runtime-context.ts",
|
|
3411
|
+
"Persisted turn-end and test-runner findings replayed into the next context message, the MCP turn_end tool and the Stop hook.",
|
|
3412
|
+
["validateAdvisoryProvenance"],
|
|
3413
|
+
// peekTurnEndFindings, consumeTurnEndFindings, peekTestFindings.
|
|
3414
|
+
["validateAdvisoryProvenance(findings.data, cwd, runtime)"],
|
|
3415
|
+
{ evidenceMin: 3 }
|
|
3416
|
+
),
|
|
3417
|
+
"index:turn-summary": labeled("index.ts", "One-line turn summary custom entry (`--lens-turn-summary`).", "Counts drained from this turn's own accumulator (`runtime.turnSummary.consume`) at the quiet window; nothing is replayed from a cache.", "live"),
|
|
3418
|
+
"lens-engine:project-scan": gated("clients/lens-engine.ts", "`pilens_project_scan` (MCP): a fresh cheap project scan.", ["applyPushedFindingPolicyByFile"], ["applyPushedFindingPolicyByFile(scan.diagnostics, cwd)"]),
|
|
3419
|
+
"mcp-server:analyze": labeled("mcp/server.ts", "`pilens_analyze` (MCP): one file's dispatch result.", "A dispatch run for this call, warm or in a fresh worker; the dispatcher applies the finding policy before it returns.", "live"),
|
|
3420
|
+
"mcp-analyze-cli:post-edit-report": labeled("mcp/analyze-cli.ts", "Claude Code PostToolUse hook report (`analyze-cli --hook`).", "Same per-call dispatch as `pilens_analyze`; its Stop-hook output is the `runtime-context:persisted-findings` replay or a fresh turn-end pass.", "live")
|
|
3024
3421
|
};
|
|
3025
3422
|
|
|
3026
3423
|
// dist/clients/cascade-format.js
|
|
3424
|
+
function formatCascadeNeighborDiagnostics(cwd, neighbors, options = {}) {
|
|
3425
|
+
const withErrors = neighbors.filter((n) => n.diagnostics.length > 0);
|
|
3426
|
+
const inconclusive = neighbors.filter((n) => n.inconclusive === true && n.diagnostics.length === 0);
|
|
3427
|
+
const uncovered = neighbors.filter((n) => n.diagnostics.length === 0 && n.inconclusive !== true && (n.unconfirmedServerIds?.length ?? 0) > 0);
|
|
3428
|
+
if (withErrors.length === 0 && inconclusive.length === 0 && uncovered.length === 0) {
|
|
3429
|
+
return "";
|
|
3430
|
+
}
|
|
3431
|
+
const noun = options.noun ?? "neighbor";
|
|
3432
|
+
let out = withErrors.length > 0 ? `\u{1F4D0} Cascade errors in ${withErrors.length} ${noun} file(s) \u2014 fix before finishing turn:` : "";
|
|
3433
|
+
for (const neighbor of withErrors) {
|
|
3434
|
+
const display = toRunnerDisplayPath(cwd, neighbor.filePath);
|
|
3435
|
+
const reason = options.includeReason ? ` reason="${neighbor.reason}"` : "";
|
|
3436
|
+
out += `
|
|
3437
|
+
<diagnostics file="${display}"${reason}>`;
|
|
3438
|
+
for (const d of neighbor.diagnostics) {
|
|
3439
|
+
const line = d.line ?? 1;
|
|
3440
|
+
const col = d.column ?? 1;
|
|
3441
|
+
const rule = d.rule ? ` rule=${d.rule}` : "";
|
|
3442
|
+
const since = options.stillPresentSince?.(neighbor, d);
|
|
3443
|
+
const label = since === void 0 ? "" : ` (still present since turn ${since})`;
|
|
3444
|
+
out += `
|
|
3445
|
+
line ${line}, col ${col}${rule}: ${d.message.split("\n")[0].slice(0, 100)}${label}`;
|
|
3446
|
+
}
|
|
3447
|
+
out += "\n</diagnostics>";
|
|
3448
|
+
}
|
|
3449
|
+
if (inconclusive.length > 0) {
|
|
3450
|
+
if (out)
|
|
3451
|
+
out += "\n";
|
|
3452
|
+
out += `\u26A0\uFE0F Cascade diagnostics inconclusive for ${inconclusive.length} ${noun} file(s) \u2014 no clean result was confirmed:`;
|
|
3453
|
+
for (const neighbor of inconclusive) {
|
|
3454
|
+
out += `
|
|
3455
|
+
${toRunnerDisplayPath(cwd, neighbor.filePath)}`;
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
if (uncovered.length > 0) {
|
|
3459
|
+
if (out)
|
|
3460
|
+
out += "\n";
|
|
3461
|
+
out += `\u26A0\uFE0F Cascade scanners did not cover ${uncovered.length} ${noun} file(s) \u2014 no findings does NOT mean clean here:`;
|
|
3462
|
+
for (const neighbor of uncovered) {
|
|
3463
|
+
const servers = (neighbor.unconfirmedServerIds ?? []).join(", ");
|
|
3464
|
+
out += `
|
|
3465
|
+
${toRunnerDisplayPath(cwd, neighbor.filePath)} (not scanned by ${servers})`;
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3468
|
+
return out;
|
|
3469
|
+
}
|
|
3470
|
+
function composeCascadeSection(block, layout, unansweredPrimaryNote = "") {
|
|
3471
|
+
const diagnosticsBlock = block && unansweredPrimaryNote ? `${block}
|
|
3472
|
+
${unansweredPrimaryNote}` : block || unansweredPrimaryNote;
|
|
3473
|
+
if (!diagnosticsBlock && !layout.coverageLine)
|
|
3474
|
+
return "";
|
|
3475
|
+
let out = !diagnosticsBlock ? "" : layout.header ? `${layout.header}
|
|
3476
|
+
${diagnosticsBlock}` : diagnosticsBlock;
|
|
3477
|
+
if (layout.truncationLine)
|
|
3478
|
+
out += `
|
|
3479
|
+
${layout.truncationLine}`;
|
|
3480
|
+
if (layout.coverageLine) {
|
|
3481
|
+
if (out)
|
|
3482
|
+
out += "\n";
|
|
3483
|
+
out += layout.coverageLine;
|
|
3484
|
+
}
|
|
3485
|
+
if (layout.policySuppressed > 0) {
|
|
3486
|
+
out += `
|
|
3487
|
+
suppressed by disposition: ${layout.policySuppressed} finding(s) (marked false-positive or won't-fix).`;
|
|
3488
|
+
}
|
|
3489
|
+
return out;
|
|
3490
|
+
}
|
|
3027
3491
|
function cascadeCarrySuffix(carriedTurns, observedAt) {
|
|
3028
3492
|
if (carriedTurns === void 0 || carriedTurns < 1)
|
|
3029
3493
|
return void 0;
|
|
3030
3494
|
const noun = carriedTurns === 1 ? "turn" : "turns";
|
|
3031
3495
|
return `(carried ${carriedTurns} ${noun} \xB7 ${formatCacheAgeLabel(observedAt)})`;
|
|
3032
3496
|
}
|
|
3497
|
+
var cascadeUnansweredPrimariesDelivered = /* @__PURE__ */ new Set();
|
|
3498
|
+
function resetCascadeUnansweredPrimariesDelivered() {
|
|
3499
|
+
cascadeUnansweredPrimariesDelivered.clear();
|
|
3500
|
+
}
|
|
3501
|
+
function markCascadeUnansweredPrimariesDelivered(serverIds) {
|
|
3502
|
+
for (const id of serverIds)
|
|
3503
|
+
cascadeUnansweredPrimariesDelivered.add(id);
|
|
3504
|
+
}
|
|
3505
|
+
function renderCascadeResult(result, shownServerIds) {
|
|
3506
|
+
const unanswered = result.unansweredPrimaries;
|
|
3507
|
+
if (!unanswered)
|
|
3508
|
+
return { text: result.formatted, lines: [], serverIds: [] };
|
|
3509
|
+
const kept = unanswered.notes.filter((note) => note.serverIds.some((id) => !cascadeUnansweredPrimariesDelivered.has(id) && !shownServerIds.has(id)));
|
|
3510
|
+
const serverIds = kept.flatMap((note) => [...note.serverIds]);
|
|
3511
|
+
for (const id of serverIds)
|
|
3512
|
+
shownServerIds.add(id);
|
|
3513
|
+
return {
|
|
3514
|
+
text: unanswered.formattedWithoutNotes,
|
|
3515
|
+
lines: kept.map((note) => note.line),
|
|
3516
|
+
serverIds
|
|
3517
|
+
};
|
|
3518
|
+
}
|
|
3519
|
+
var MAX_PENDING_NEIGHBORS = 256;
|
|
3520
|
+
var pendingNeighbors = new BoundedFifoMap(MAX_PENDING_NEIGHBORS);
|
|
3521
|
+
function cascadeErrorKey(diagnostic) {
|
|
3522
|
+
return [
|
|
3523
|
+
diagnostic.id,
|
|
3524
|
+
diagnostic.rule ?? "",
|
|
3525
|
+
diagnostic.line ?? 0,
|
|
3526
|
+
diagnostic.column ?? 0,
|
|
3527
|
+
diagnostic.message
|
|
3528
|
+
].join(":");
|
|
3529
|
+
}
|
|
3530
|
+
function cascadeStillPresentSince(filePath, diagnostic, turn) {
|
|
3531
|
+
const first = pendingNeighbors.get(normalizeMapKey(filePath))?.errors.get(cascadeErrorKey(diagnostic));
|
|
3532
|
+
return first !== void 0 && first < turn ? first : void 0;
|
|
3533
|
+
}
|
|
3534
|
+
function recordDeliveredCascadeNeighbor(filePath, diagnostics, turn, checkedAt) {
|
|
3535
|
+
const key2 = normalizeMapKey(filePath);
|
|
3536
|
+
const previous = pendingNeighbors.get(key2);
|
|
3537
|
+
const errors = /* @__PURE__ */ new Map();
|
|
3538
|
+
for (const d of diagnostics) {
|
|
3539
|
+
const k = cascadeErrorKey(d);
|
|
3540
|
+
errors.set(k, previous?.errors.get(k) ?? turn);
|
|
3541
|
+
}
|
|
3542
|
+
pendingNeighbors.delete(key2);
|
|
3543
|
+
if (errors.size === 0)
|
|
3544
|
+
return;
|
|
3545
|
+
if (pendingNeighbors.set(key2, { filePath, errors, checkedAt }).length > 0) {
|
|
3546
|
+
recordDegradationOnce({
|
|
3547
|
+
kind: "cascade-pending-neighbors-evicted",
|
|
3548
|
+
subject: `cap=${MAX_PENDING_NEIGHBORS}`,
|
|
3549
|
+
reason: "the pending cascade neighbour-error record hit its cap; the oldest neighbour's errors are no longer re-served"
|
|
3550
|
+
});
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
function forgetCascadePendingNeighbor(filePath, observedAt) {
|
|
3554
|
+
const key2 = normalizeMapKey(filePath);
|
|
3555
|
+
const entry = pendingNeighbors.get(key2);
|
|
3556
|
+
if (!entry)
|
|
3557
|
+
return;
|
|
3558
|
+
if (observedAt !== void 0 && observedAt <= entry.checkedAt)
|
|
3559
|
+
return;
|
|
3560
|
+
pendingNeighbors.delete(key2);
|
|
3561
|
+
}
|
|
3562
|
+
function listCascadePendingNeighbors() {
|
|
3563
|
+
return [...pendingNeighbors.values()].map((entry) => ({
|
|
3564
|
+
filePath: entry.filePath,
|
|
3565
|
+
errorCount: entry.errors.size,
|
|
3566
|
+
checkedAt: entry.checkedAt
|
|
3567
|
+
}));
|
|
3568
|
+
}
|
|
3569
|
+
function resetCascadePendingNeighbors() {
|
|
3570
|
+
pendingNeighbors.clear();
|
|
3571
|
+
}
|
|
3033
3572
|
|
|
3034
3573
|
// dist/clients/cascade-logger.js
|
|
3035
3574
|
import * as path5 from "node:path";
|
|
@@ -3142,33 +3681,152 @@ function createDiagnosticTracker() {
|
|
|
3142
3681
|
}
|
|
3143
3682
|
|
|
3144
3683
|
// dist/clients/lsp/cascade-tier.js
|
|
3684
|
+
var MAX_OUTSTANDING_TOUCHES = 256;
|
|
3145
3685
|
var OUTSTANDING_TOUCH_MAX_AGE_MS = 15 * 6e4;
|
|
3146
|
-
var _outstandingTouches =
|
|
3686
|
+
var _outstandingTouches = new BoundedFifoMap(MAX_OUTSTANDING_TOUCHES);
|
|
3147
3687
|
var _expiredSinceLastSweep = 0;
|
|
3148
3688
|
var _evictedSinceLastSweep = 0;
|
|
3689
|
+
var MAX_LOGGED_PATHS = 20;
|
|
3690
|
+
function pruneExpiredOutstandingTouches(now, guard, reads = /* @__PURE__ */ new Map()) {
|
|
3691
|
+
const expired = [];
|
|
3692
|
+
for (const [key2, touch] of _outstandingTouches) {
|
|
3693
|
+
if (now - touch.touchedAt <= OUTSTANDING_TOUCH_MAX_AGE_MS)
|
|
3694
|
+
break;
|
|
3695
|
+
_outstandingTouches.delete(key2);
|
|
3696
|
+
_expiredSinceLastSweep++;
|
|
3697
|
+
expired.push(touch);
|
|
3698
|
+
}
|
|
3699
|
+
if (expired.length === 0)
|
|
3700
|
+
return;
|
|
3701
|
+
let found = 0;
|
|
3702
|
+
let clean = 0;
|
|
3703
|
+
for (const touch of expired) {
|
|
3704
|
+
const outcome = readTouchedClient(touch, now, reads);
|
|
3705
|
+
if (!outcome)
|
|
3706
|
+
continue;
|
|
3707
|
+
if (outcome.outcome === "resolved-found")
|
|
3708
|
+
found++;
|
|
3709
|
+
else
|
|
3710
|
+
clean++;
|
|
3711
|
+
deliverResolvedOutcome(outcome, guard);
|
|
3712
|
+
}
|
|
3713
|
+
logCascade({
|
|
3714
|
+
phase: "cascade_tier3_expired",
|
|
3715
|
+
filePath: "<cascade-registry>",
|
|
3716
|
+
metadata: {
|
|
3717
|
+
count: expired.length,
|
|
3718
|
+
found,
|
|
3719
|
+
clean,
|
|
3720
|
+
unanswered: expired.length - found - clean,
|
|
3721
|
+
maxAgeCapMs: OUTSTANDING_TOUCH_MAX_AGE_MS,
|
|
3722
|
+
paths: expired.slice(0, MAX_LOGGED_PATHS).map((t) => t.filePath),
|
|
3723
|
+
...expired.length > MAX_LOGGED_PATHS && {
|
|
3724
|
+
pathsTruncated: expired.length - MAX_LOGGED_PATHS
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
});
|
|
3728
|
+
}
|
|
3729
|
+
function readTouchedClient(touch, now, reads) {
|
|
3730
|
+
const client = touch.client?.deref();
|
|
3731
|
+
if (!client || client.serverId !== touch.serverId)
|
|
3732
|
+
return void 0;
|
|
3733
|
+
if (client.isAlive?.() === false)
|
|
3734
|
+
return void 0;
|
|
3735
|
+
let all = reads.get(client);
|
|
3736
|
+
if (all === void 0) {
|
|
3737
|
+
all = client.getAllDiagnostics();
|
|
3738
|
+
reads.set(client, all);
|
|
3739
|
+
}
|
|
3740
|
+
const entry = all.get(normalizeMapKey(touch.filePath));
|
|
3741
|
+
if (!entry || entry.ts <= touch.touchedAt)
|
|
3742
|
+
return void 0;
|
|
3743
|
+
const found = entry.diags.length > 0;
|
|
3744
|
+
return {
|
|
3745
|
+
filePath: touch.filePath,
|
|
3746
|
+
serverId: touch.serverId,
|
|
3747
|
+
outcome: found ? "resolved-found" : "resolved-clean",
|
|
3748
|
+
ageMs: now - touch.touchedAt,
|
|
3749
|
+
diagnosticCount: entry.diags.length,
|
|
3750
|
+
publishedAt: entry.ts,
|
|
3751
|
+
touchedAt: touch.touchedAt,
|
|
3752
|
+
...found && { diagnostics: entry.diags }
|
|
3753
|
+
};
|
|
3754
|
+
}
|
|
3755
|
+
function deliverResolvedOutcome(o, guard) {
|
|
3756
|
+
try {
|
|
3757
|
+
if (o.outcome === "resolved-found" && o.diagnostics?.length) {
|
|
3758
|
+
const neighbor = {
|
|
3759
|
+
filePath: o.filePath,
|
|
3760
|
+
serverId: o.serverId,
|
|
3761
|
+
diagnostics: o.diagnostics,
|
|
3762
|
+
...o.publishedAt !== void 0 ? { publishedAt: o.publishedAt } : {},
|
|
3763
|
+
...o.touchedAt !== void 0 ? { touchedAt: o.touchedAt } : {}
|
|
3764
|
+
};
|
|
3765
|
+
const deliver = () => _reconcileOptions.onResolvedFound?.(neighbor);
|
|
3766
|
+
if (guard)
|
|
3767
|
+
guard.guardedWrite(o.filePath, deliver);
|
|
3768
|
+
else
|
|
3769
|
+
deliver();
|
|
3770
|
+
} else if (o.outcome === "resolved-clean" && o.publishedAt != null) {
|
|
3771
|
+
_reconcileOptions.onResolvedClean?.({
|
|
3772
|
+
filePath: o.filePath,
|
|
3773
|
+
serverId: o.serverId,
|
|
3774
|
+
publishedAt: o.publishedAt
|
|
3775
|
+
});
|
|
3776
|
+
}
|
|
3777
|
+
} catch {
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3149
3780
|
function resetCascadeTierSessionState() {
|
|
3781
|
+
const dropped = _outstandingTouches.size;
|
|
3150
3782
|
_outstandingTouches.clear();
|
|
3151
3783
|
_expiredSinceLastSweep = 0;
|
|
3152
3784
|
_evictedSinceLastSweep = 0;
|
|
3785
|
+
if (dropped > 0) {
|
|
3786
|
+
logCascade({
|
|
3787
|
+
phase: "cascade_tier3_dropped",
|
|
3788
|
+
filePath: "<session-reset>",
|
|
3789
|
+
metadata: { count: dropped }
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3153
3792
|
}
|
|
3793
|
+
function peekOutstandingCascadeTouches(guard) {
|
|
3794
|
+
const now = Date.now();
|
|
3795
|
+
const reads = /* @__PURE__ */ new Map();
|
|
3796
|
+
pruneExpiredOutstandingTouches(now, guard, reads);
|
|
3797
|
+
const count = _outstandingTouches.size;
|
|
3798
|
+
if (count === 0)
|
|
3799
|
+
return;
|
|
3800
|
+
let found = 0;
|
|
3801
|
+
let clean = 0;
|
|
3802
|
+
for (const [key2, touch] of _outstandingTouches) {
|
|
3803
|
+
const outcome = readTouchedClient(touch, now, reads);
|
|
3804
|
+
if (!outcome)
|
|
3805
|
+
continue;
|
|
3806
|
+
_outstandingTouches.delete(key2);
|
|
3807
|
+
if (outcome.outcome === "resolved-found")
|
|
3808
|
+
found++;
|
|
3809
|
+
else
|
|
3810
|
+
clean++;
|
|
3811
|
+
deliverResolvedOutcome(outcome, guard);
|
|
3812
|
+
}
|
|
3813
|
+
logCascade({
|
|
3814
|
+
phase: "cascade_tier3_peek",
|
|
3815
|
+
filePath: "<turn_end>",
|
|
3816
|
+
metadata: {
|
|
3817
|
+
count,
|
|
3818
|
+
found,
|
|
3819
|
+
clean,
|
|
3820
|
+
outstanding: _outstandingTouches.size
|
|
3821
|
+
}
|
|
3822
|
+
});
|
|
3823
|
+
}
|
|
3824
|
+
var _reconcileOptions = {};
|
|
3154
3825
|
|
|
3155
3826
|
// dist/clients/dispatch/runners/ast-grep-napi.js
|
|
3156
|
-
import * as
|
|
3827
|
+
import * as fs5 from "node:fs";
|
|
3157
3828
|
import * as path6 from "node:path";
|
|
3158
3829
|
|
|
3159
|
-
// dist/clients/deps/ast-grep-napi.js
|
|
3160
|
-
import { createRequire } from "node:module";
|
|
3161
|
-
import { pathToFileURL } from "node:url";
|
|
3162
|
-
var _require = createRequire(import.meta.url);
|
|
3163
|
-
function loadAstGrepNapi() {
|
|
3164
|
-
try {
|
|
3165
|
-
const entry = _require.resolve("@ast-grep/napi");
|
|
3166
|
-
return import(pathToFileURL(entry).href);
|
|
3167
|
-
} catch {
|
|
3168
|
-
return import("@ast-grep/napi");
|
|
3169
|
-
}
|
|
3170
|
-
}
|
|
3171
|
-
|
|
3172
3830
|
// dist/clients/dispatch/priorities.js
|
|
3173
3831
|
var PRIORITY = {
|
|
3174
3832
|
LSP_PRIMARY: 4,
|
|
@@ -3185,6 +3843,66 @@ var PRIORITY = {
|
|
|
3185
3843
|
DEEP_LANGUAGE_ANALYSIS: 50
|
|
3186
3844
|
};
|
|
3187
3845
|
|
|
3846
|
+
// dist/clients/dispatch/runners/ast-grep-literal-anchors.js
|
|
3847
|
+
var PATTERN_WORD = /\$?[A-Za-z_]\w*/g;
|
|
3848
|
+
var LITERAL_REGEX = /^\^?((?:[A-Za-z0-9_"'`:\- =!<>/@#%&,;~]|\\\.)+)\$?$/;
|
|
3849
|
+
var RELATIONAL_KEYS = ["has", "inside", "follows", "precedes"];
|
|
3850
|
+
function ownLiterals(node) {
|
|
3851
|
+
const literals = [];
|
|
3852
|
+
if (typeof node.pattern === "string") {
|
|
3853
|
+
for (const word of node.pattern.match(PATTERN_WORD) ?? []) {
|
|
3854
|
+
if (!word.startsWith("$"))
|
|
3855
|
+
literals.push(word);
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
const regex = typeof node.regex === "string" ? node.regex : "";
|
|
3859
|
+
const literal = LITERAL_REGEX.exec(regex)?.[1];
|
|
3860
|
+
if (literal)
|
|
3861
|
+
literals.push(literal.replaceAll(String.raw`\.`, "."));
|
|
3862
|
+
return literals;
|
|
3863
|
+
}
|
|
3864
|
+
function anyOf(branches) {
|
|
3865
|
+
if (branches.length === 0 || branches.includes(true))
|
|
3866
|
+
return true;
|
|
3867
|
+
return { or: branches };
|
|
3868
|
+
}
|
|
3869
|
+
function requirementOf(node, utils, resolving) {
|
|
3870
|
+
if (!node || typeof node !== "object")
|
|
3871
|
+
return true;
|
|
3872
|
+
const of = (child) => requirementOf(child, utils, resolving);
|
|
3873
|
+
const parts = [
|
|
3874
|
+
...ownLiterals(node),
|
|
3875
|
+
...RELATIONAL_KEYS.map((key2) => of(node[key2])),
|
|
3876
|
+
...Array.isArray(node.all) ? node.all.map(of) : [],
|
|
3877
|
+
Array.isArray(node.any) ? anyOf(node.any.map(of)) : true
|
|
3878
|
+
];
|
|
3879
|
+
const name = node.matches;
|
|
3880
|
+
if (typeof name === "string" && utils != null && Object.hasOwn(utils, name) && !resolving.has(name)) {
|
|
3881
|
+
parts.push(requirementOf(utils[name], utils, /* @__PURE__ */ new Set([...resolving, name])));
|
|
3882
|
+
}
|
|
3883
|
+
const required = parts.filter((part) => part !== true);
|
|
3884
|
+
return required.length === 0 ? true : { and: required };
|
|
3885
|
+
}
|
|
3886
|
+
function satisfied(requirement, text) {
|
|
3887
|
+
if (requirement === true)
|
|
3888
|
+
return true;
|
|
3889
|
+
if (typeof requirement === "string")
|
|
3890
|
+
return text.includes(requirement);
|
|
3891
|
+
if ("and" in requirement) {
|
|
3892
|
+
return requirement.and.every((part) => satisfied(part, text));
|
|
3893
|
+
}
|
|
3894
|
+
return requirement.or.some((part) => satisfied(part, text));
|
|
3895
|
+
}
|
|
3896
|
+
var requirements = /* @__PURE__ */ new WeakMap();
|
|
3897
|
+
function ruleCanMatchText(rule, text) {
|
|
3898
|
+
let requirement = requirements.get(rule);
|
|
3899
|
+
if (requirement === void 0) {
|
|
3900
|
+
requirement = requirementOf(rule.rule, rule.utils, /* @__PURE__ */ new Set());
|
|
3901
|
+
requirements.set(rule, requirement);
|
|
3902
|
+
}
|
|
3903
|
+
return satisfied(requirement, text);
|
|
3904
|
+
}
|
|
3905
|
+
|
|
3188
3906
|
// dist/clients/dispatch/runners/ast-grep-napi.js
|
|
3189
3907
|
var defaultUnsupportedLanguageLog = /* @__PURE__ */ new Set();
|
|
3190
3908
|
var UNSUPPORTED_RULE_ID_SAMPLE_SIZE = 5;
|
|
@@ -3702,12 +4420,19 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3702
4420
|
}
|
|
3703
4421
|
if (!rule.rule)
|
|
3704
4422
|
continue;
|
|
4423
|
+
if (options.content !== void 0 && !ruleCanMatchText(rule, options.content)) {
|
|
4424
|
+
continue;
|
|
4425
|
+
}
|
|
3705
4426
|
try {
|
|
3706
4427
|
const scopes = runsInsideHtmlScript ? htmlInjections.map((injection) => ({
|
|
3707
4428
|
root: injection.root,
|
|
3708
4429
|
position(match) {
|
|
3709
4430
|
const start = match.range().start;
|
|
3710
4431
|
return filePositionForIndex(fileLineStarts, injection.startIndex + start.index);
|
|
4432
|
+
},
|
|
4433
|
+
endLine(match) {
|
|
4434
|
+
const end = match.range().end;
|
|
4435
|
+
return filePositionForIndex(fileLineStarts, injection.startIndex + end.index).line;
|
|
3711
4436
|
}
|
|
3712
4437
|
})) : [
|
|
3713
4438
|
{
|
|
@@ -3715,6 +4440,9 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3715
4440
|
position(match) {
|
|
3716
4441
|
const start = match.range().start;
|
|
3717
4442
|
return { line: start.line, column: start.column };
|
|
4443
|
+
},
|
|
4444
|
+
endLine(match) {
|
|
4445
|
+
return match.range().end.line;
|
|
3718
4446
|
}
|
|
3719
4447
|
}
|
|
3720
4448
|
];
|
|
@@ -3724,7 +4452,9 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3724
4452
|
if (rule.utils)
|
|
3725
4453
|
nativeConfig.utils = rule.utils;
|
|
3726
4454
|
const collected = [];
|
|
4455
|
+
const withheld = [];
|
|
3727
4456
|
let rejectLogged = false;
|
|
4457
|
+
const editScoped = options.modifiedRanges !== void 0 && normalizeRuleSeverity(rule.severity) === "error";
|
|
3728
4458
|
for (const scope of scopes) {
|
|
3729
4459
|
let found;
|
|
3730
4460
|
try {
|
|
@@ -3739,19 +4469,23 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3739
4469
|
for (const match of found) {
|
|
3740
4470
|
if (collected.length >= maxMatchesPerRule)
|
|
3741
4471
|
break;
|
|
3742
|
-
|
|
4472
|
+
const position = scope.position(match);
|
|
4473
|
+
if (editScoped && !spanOverlapsModifiedRanges(position.line + 1, scope.endLine(match) + 1, options.modifiedRanges)) {
|
|
4474
|
+
if (withheld.length < maxMatchesPerRule)
|
|
4475
|
+
withheld.push({ position });
|
|
4476
|
+
continue;
|
|
4477
|
+
}
|
|
4478
|
+
collected.push({ match, position });
|
|
3743
4479
|
}
|
|
3744
4480
|
if (collected.length >= maxMatchesPerRule)
|
|
3745
4481
|
break;
|
|
3746
4482
|
}
|
|
3747
|
-
|
|
3748
|
-
if (diagnostics.length >= maxTotalDiagnostics)
|
|
3749
|
-
break;
|
|
4483
|
+
const toDiagnostic3 = (position) => {
|
|
3750
4484
|
const severity = normalizeRuleSeverity(rule.severity);
|
|
3751
4485
|
const semantic = severity === "error" ? "blocking" : "warning";
|
|
3752
4486
|
const defectClass = classifyDefect(rule.id, "ast-grep-napi", rule.message || rule.id);
|
|
3753
4487
|
const ruleFix = explicitRuleFixSuggestion(rule);
|
|
3754
|
-
|
|
4488
|
+
return {
|
|
3755
4489
|
id: `ast-grep-napi-${position.line}-${rule.id}`,
|
|
3756
4490
|
message: `[${rule.metadata?.category || "slop"}] ${rule.message || rule.id}`,
|
|
3757
4491
|
filePath,
|
|
@@ -3766,7 +4500,15 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3766
4500
|
autoFixAvailable: false,
|
|
3767
4501
|
fixKind: ruleFix ? "suggestion" : void 0,
|
|
3768
4502
|
fixSuggestion: semantic === "blocking" ? ruleFix ?? defaultFixSuggestion(defectClass, rule.id) : ruleFix
|
|
3769
|
-
}
|
|
4503
|
+
};
|
|
4504
|
+
};
|
|
4505
|
+
for (const { position } of collected) {
|
|
4506
|
+
if (diagnostics.length >= maxTotalDiagnostics)
|
|
4507
|
+
break;
|
|
4508
|
+
diagnostics.push(toDiagnostic3(position));
|
|
4509
|
+
}
|
|
4510
|
+
for (const { position } of withheld) {
|
|
4511
|
+
options.outOfEditScope?.push(toDiagnostic3(position));
|
|
3770
4512
|
}
|
|
3771
4513
|
if (diagnostics.length >= maxTotalDiagnostics)
|
|
3772
4514
|
break;
|
|
@@ -3788,8 +4530,10 @@ var astGrepNapiRunner = {
|
|
|
3788
4530
|
}
|
|
3789
4531
|
const astGrepLspEnabled = enabledAuxiliaryLspServerIds((f) => ctx.pi?.getFlag?.(f)).includes("ast-grep");
|
|
3790
4532
|
const astGrepLspPublished = astGrepLspEnabled ? await hasAuxiliaryLspPublishedForRoot("ast-grep", ctx.filePath) : false;
|
|
3791
|
-
|
|
3792
|
-
|
|
4533
|
+
const coveredByServer = astGrepLspEnabled && astGrepLspPublished;
|
|
4534
|
+
if (coveredByServer && !ctx.recordedRunnerIds?.has("ast-grep-napi")) {
|
|
4535
|
+
const coveragePending = hasPendingAuxiliaryCoverage(ctx.filePath, "ast-grep");
|
|
4536
|
+
if (coveragePending) {
|
|
3793
4537
|
incrementDegradationCount({
|
|
3794
4538
|
kind: "aux-runner-findings-lost",
|
|
3795
4539
|
subject: "ast-grep",
|
|
@@ -3798,13 +4542,23 @@ var astGrepNapiRunner = {
|
|
|
3798
4542
|
reason: `Gate B skipped napi: pending late-auxiliary pair from an EARLIER touch remains undelivered while prior publication satisfies per-file gate (file: ${ctx.filePath})`
|
|
3799
4543
|
});
|
|
3800
4544
|
}
|
|
3801
|
-
return {
|
|
4545
|
+
return {
|
|
4546
|
+
status: "skipped",
|
|
4547
|
+
diagnostics: [],
|
|
4548
|
+
semantic: "none",
|
|
4549
|
+
// Round 7: the verdict holds only if the server's host answered.
|
|
4550
|
+
...coveragePending ? {} : {
|
|
4551
|
+
skipReason: "covered-by-primary",
|
|
4552
|
+
coveredBy: { runnerId: "lsp", serverId: "ast-grep" }
|
|
4553
|
+
},
|
|
4554
|
+
...ctx.blockingOnly && ctx.modifiedRanges?.length ? { editScopedVerdict: true } : {}
|
|
4555
|
+
};
|
|
3802
4556
|
}
|
|
3803
4557
|
const sgModule = await loadSg();
|
|
3804
4558
|
if (!sgModule) {
|
|
3805
4559
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3806
4560
|
}
|
|
3807
|
-
if (!
|
|
4561
|
+
if (!fs5.existsSync(ctx.filePath)) {
|
|
3808
4562
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3809
4563
|
}
|
|
3810
4564
|
const lang = getLang(ctx.filePath, sgModule);
|
|
@@ -3813,7 +4567,7 @@ var astGrepNapiRunner = {
|
|
|
3813
4567
|
}
|
|
3814
4568
|
let stats;
|
|
3815
4569
|
try {
|
|
3816
|
-
stats =
|
|
4570
|
+
stats = fs5.statSync(ctx.filePath);
|
|
3817
4571
|
} catch {
|
|
3818
4572
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3819
4573
|
}
|
|
@@ -3826,7 +4580,7 @@ var astGrepNapiRunner = {
|
|
|
3826
4580
|
content = contentFromFacts;
|
|
3827
4581
|
} else {
|
|
3828
4582
|
try {
|
|
3829
|
-
content =
|
|
4583
|
+
content = fs5.readFileSync(ctx.filePath, "utf-8");
|
|
3830
4584
|
} catch {
|
|
3831
4585
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3832
4586
|
}
|
|
@@ -3848,10 +4602,16 @@ var astGrepNapiRunner = {
|
|
|
3848
4602
|
recordNapiFallbackCoverage(ctx.filePath);
|
|
3849
4603
|
clearPendingAuxiliaryCoverage(ctx.filePath, "ast-grep");
|
|
3850
4604
|
}
|
|
4605
|
+
const outOfEditScope = [];
|
|
3851
4606
|
const diagnostics = evaluateAstGrepRules(ctx.filePath, rootNode, ctx.cwd, ctx.kind, {
|
|
3852
4607
|
blockingOnly: runningAsLspSubstitute ? false : ctx.blockingOnly,
|
|
3853
4608
|
projectRoot: ctx.projectRoot,
|
|
3854
4609
|
rulePolicy: ctx.rulePolicy,
|
|
4610
|
+
// #4481: keyed off the per-edit pass, not the substitute floor
|
|
4611
|
+
// above, so a pre-existing blocker on an unchanged line never
|
|
4612
|
+
// STOPs the write in either role.
|
|
4613
|
+
modifiedRanges: ctx.blockingOnly ? ctx.modifiedRanges : void 0,
|
|
4614
|
+
outOfEditScope,
|
|
3855
4615
|
log: (message) => ctx.log(message),
|
|
3856
4616
|
content,
|
|
3857
4617
|
sgModule
|
|
@@ -3881,10 +4641,16 @@ var astGrepNapiRunner = {
|
|
|
3881
4641
|
} else if (diagnostics.length > 0) {
|
|
3882
4642
|
semantic = "warning";
|
|
3883
4643
|
}
|
|
3884
|
-
return
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
4644
|
+
return {
|
|
4645
|
+
...findingsResult(diagnostics, {
|
|
4646
|
+
status: hasBlocking ? "failed" : "succeeded",
|
|
4647
|
+
semantic
|
|
4648
|
+
}),
|
|
4649
|
+
...outOfEditScope.length > 0 && { outOfEditScope },
|
|
4650
|
+
...coveredByServer && {
|
|
4651
|
+
coveredBy: { runnerId: "lsp", serverId: "ast-grep" }
|
|
4652
|
+
}
|
|
4653
|
+
};
|
|
3888
4654
|
}
|
|
3889
4655
|
};
|
|
3890
4656
|
var ast_grep_napi_default = astGrepNapiRunner;
|
|
@@ -4425,7 +5191,7 @@ var biomeCheckJsonRunner = {
|
|
|
4425
5191
|
var biome_check_default = biomeCheckJsonRunner;
|
|
4426
5192
|
|
|
4427
5193
|
// dist/clients/dispatch/runners/cpp-check.js
|
|
4428
|
-
import * as
|
|
5194
|
+
import * as fs6 from "node:fs";
|
|
4429
5195
|
import * as path9 from "node:path";
|
|
4430
5196
|
var compilerCheckers = {
|
|
4431
5197
|
clang: createAvailabilityChecker("clang", ".exe"),
|
|
@@ -4464,7 +5230,7 @@ var CPP_HEADER_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4464
5230
|
]);
|
|
4465
5231
|
function headerLooksLikeCpp(absPath) {
|
|
4466
5232
|
try {
|
|
4467
|
-
const content =
|
|
5233
|
+
const content = fs6.readFileSync(absPath, "utf-8");
|
|
4468
5234
|
return /\b(namespace|template|class|constexpr|concept|using)\b|std::|\b(public|private|protected)\s*:/.test(content);
|
|
4469
5235
|
} catch {
|
|
4470
5236
|
return false;
|
|
@@ -4615,7 +5381,7 @@ var cpp_check_default = cppCheckRunner;
|
|
|
4615
5381
|
|
|
4616
5382
|
// dist/clients/dispatch/runners/credo.js
|
|
4617
5383
|
import * as path10 from "node:path";
|
|
4618
|
-
import * as
|
|
5384
|
+
import * as fs7 from "node:fs";
|
|
4619
5385
|
var CREDO_PROBE_BUDGET_MS = 1e4;
|
|
4620
5386
|
var probeCredo = createCwdCachedProbe((cwd) => safeSpawnAsync("mix", ["credo", "--version"], {
|
|
4621
5387
|
timeout: CREDO_PROBE_BUDGET_MS,
|
|
@@ -4641,7 +5407,7 @@ function parseCredoJson(raw, fallbackPath, cwd) {
|
|
|
4641
5407
|
}
|
|
4642
5408
|
}
|
|
4643
5409
|
function hasMixExs(cwd) {
|
|
4644
|
-
return
|
|
5410
|
+
return fs7.existsSync(path10.join(cwd, "mix.exs"));
|
|
4645
5411
|
}
|
|
4646
5412
|
var credoRunner = {
|
|
4647
5413
|
id: "credo",
|
|
@@ -4678,7 +5444,7 @@ var credoRunner = {
|
|
|
4678
5444
|
var credo_default = credoRunner;
|
|
4679
5445
|
|
|
4680
5446
|
// dist/clients/dispatch/runners/cue-vet.js
|
|
4681
|
-
import * as
|
|
5447
|
+
import * as fs8 from "node:fs";
|
|
4682
5448
|
import * as path11 from "node:path";
|
|
4683
5449
|
var cue = createAvailabilityChecker("cue", ".exe", ["version"]);
|
|
4684
5450
|
function parseCueVetOutput(raw) {
|
|
@@ -4783,7 +5549,7 @@ var cueVetRunner = {
|
|
|
4783
5549
|
const singleFileArgs = ["vet", "-c=false", `./${fileName}`];
|
|
4784
5550
|
let touchedContent = null;
|
|
4785
5551
|
try {
|
|
4786
|
-
touchedContent =
|
|
5552
|
+
touchedContent = fs8.readFileSync(absPath, "utf8");
|
|
4787
5553
|
} catch {
|
|
4788
5554
|
touchedContent = null;
|
|
4789
5555
|
}
|
|
@@ -4988,8 +5754,11 @@ var dartAnalyzeRunner = {
|
|
|
4988
5754
|
const parsed = parseToolRun("dart-analyze", {
|
|
4989
5755
|
result,
|
|
4990
5756
|
output: raw,
|
|
4991
|
-
// EXIT TABLE (Dart 3.
|
|
4992
|
-
|
|
5757
|
+
// EXIT TABLE (Dart 3.13 measured fixture, tests/fixtures/runner-output/
|
|
5758
|
+
// dart-analyze): 0 clean; 1 infos; 2 warnings; 3 errors; other nonzero
|
|
5759
|
+
// rejected. The 3.5 table stopped at 2, so a file with a compile error
|
|
5760
|
+
// read as a rejected invocation and its findings were dropped.
|
|
5761
|
+
exitCodes: { ran: [1, 2, 3] }
|
|
4993
5762
|
}, (out) => parseDartMachineOutput(out, ctx.filePath, cwd));
|
|
4994
5763
|
if (parsed.skipped)
|
|
4995
5764
|
return parsed.skipped;
|
|
@@ -5004,7 +5773,7 @@ var dartAnalyzeRunner = {
|
|
|
5004
5773
|
var dart_analyze_default = dartAnalyzeRunner;
|
|
5005
5774
|
|
|
5006
5775
|
// dist/clients/dispatch/runners/detekt.js
|
|
5007
|
-
import * as
|
|
5776
|
+
import * as fs9 from "node:fs";
|
|
5008
5777
|
import * as path13 from "node:path";
|
|
5009
5778
|
var detekt = createAvailabilityChecker("detekt", ".bat");
|
|
5010
5779
|
var DETEKT_CONFIG_CANDIDATES = [
|
|
@@ -5078,7 +5847,7 @@ var DETEKT_FIXABLE_RULES = /* @__PURE__ */ new Set([
|
|
|
5078
5847
|
function findDetektConfig(cwd) {
|
|
5079
5848
|
for (const candidate of DETEKT_CONFIG_CANDIDATES) {
|
|
5080
5849
|
const full = path13.join(cwd, candidate);
|
|
5081
|
-
if (
|
|
5850
|
+
if (fs9.existsSync(full))
|
|
5082
5851
|
return full;
|
|
5083
5852
|
}
|
|
5084
5853
|
return void 0;
|
|
@@ -5157,11 +5926,11 @@ var detektRunner = {
|
|
|
5157
5926
|
var detekt_default = detektRunner;
|
|
5158
5927
|
|
|
5159
5928
|
// dist/clients/dispatch/runners/dotnet-build.js
|
|
5160
|
-
import * as
|
|
5929
|
+
import * as fs10 from "node:fs";
|
|
5161
5930
|
import * as path14 from "node:path";
|
|
5162
5931
|
var dotnet = createAvailabilityChecker("dotnet", ".exe");
|
|
5163
5932
|
function findProjectTarget(cwd) {
|
|
5164
|
-
const entries =
|
|
5933
|
+
const entries = fs10.readdirSync(cwd);
|
|
5165
5934
|
const solution = entries.find((entry) => /\.(sln|slnx)$/i.test(entry));
|
|
5166
5935
|
if (solution)
|
|
5167
5936
|
return solution;
|
|
@@ -5311,12 +6080,12 @@ ${result.stderr ?? ""}`.trim();
|
|
|
5311
6080
|
var dotnet_build_default = dotnetBuildRunner;
|
|
5312
6081
|
|
|
5313
6082
|
// dist/clients/dispatch/runners/elixir-check.js
|
|
5314
|
-
import * as
|
|
6083
|
+
import * as fs11 from "node:fs";
|
|
5315
6084
|
import * as path15 from "node:path";
|
|
5316
6085
|
var mix = createAvailabilityChecker("mix", ".bat");
|
|
5317
6086
|
var elixirc = createAvailabilityChecker("elixirc", ".bat");
|
|
5318
6087
|
function hasMixExs2(cwd) {
|
|
5319
|
-
return
|
|
6088
|
+
return fs11.existsSync(path15.join(cwd, "mix.exs"));
|
|
5320
6089
|
}
|
|
5321
6090
|
var ELIXIR_SNIPPET_LOCATION = /└─\s+(.+?):(\d+)(?::(\d+))?(?::|$)/;
|
|
5322
6091
|
function parseElixirOutput(raw, filePath, cwd = process.cwd()) {
|
|
@@ -5416,7 +6185,7 @@ var elixirCheckRunner = {
|
|
|
5416
6185
|
args = ["compile", "--warnings-as-errors"];
|
|
5417
6186
|
} else if (await elixirc.isAvailableAsync(cwd)) {
|
|
5418
6187
|
const outDir = path15.join(getProjectDataDir(cwd), "elixir-check");
|
|
5419
|
-
|
|
6188
|
+
fs11.mkdirSync(outDir, { recursive: true });
|
|
5420
6189
|
command = "elixirc";
|
|
5421
6190
|
args = ["-o", outDir, absPath];
|
|
5422
6191
|
}
|
|
@@ -5751,9 +6520,10 @@ var parseRuffOutput = createLineParser({
|
|
|
5751
6520
|
autoFixAvailable: ruffAutofix?.safePipelineAutofix ?? false,
|
|
5752
6521
|
fixKind: ruffAutofix?.fixKind === "none" ? void 0 : ruffAutofix?.fixKind
|
|
5753
6522
|
});
|
|
6523
|
+
var GO_VET_LINE = /^(?:vet:\s+)?(.+?):(\d+):(\d+):\s*(.+)/;
|
|
5754
6524
|
var parseGoVetOutput = createLineParser({
|
|
5755
6525
|
tool: "go-vet",
|
|
5756
|
-
regex:
|
|
6526
|
+
regex: GO_VET_LINE,
|
|
5757
6527
|
extractMessage: (m) => m[4],
|
|
5758
6528
|
generateId: (m) => `go-vet-${m[2]}`,
|
|
5759
6529
|
defectClass: "correctness"
|
|
@@ -5795,7 +6565,7 @@ var goVetRunner = {
|
|
|
5795
6565
|
}
|
|
5796
6566
|
const absTarget = resolve14(ctx.filePath);
|
|
5797
6567
|
const relevant = raw.split("\n").filter((line) => {
|
|
5798
|
-
const m = line.match(
|
|
6568
|
+
const m = line.match(GO_VET_LINE);
|
|
5799
6569
|
return m != null && pathsEqual(resolve14(cwd, m[1].trim()), absTarget);
|
|
5800
6570
|
}).join("\n");
|
|
5801
6571
|
const diagnostics = parseGoVetOutput(relevant, ctx.filePath, cwd);
|
|
@@ -5807,6 +6577,16 @@ var go_vet_default = goVetRunner;
|
|
|
5807
6577
|
// dist/clients/dispatch/runners/golangci-lint.js
|
|
5808
6578
|
import * as path19 from "node:path";
|
|
5809
6579
|
var golangci = createAvailabilityChecker("golangci-lint", ".exe");
|
|
6580
|
+
var OTHER_OUTPUT_FORMATS = [
|
|
6581
|
+
"text",
|
|
6582
|
+
"tab",
|
|
6583
|
+
"html",
|
|
6584
|
+
"checkstyle",
|
|
6585
|
+
"code-climate",
|
|
6586
|
+
"junit-xml",
|
|
6587
|
+
"teamcity",
|
|
6588
|
+
"sarif"
|
|
6589
|
+
];
|
|
5810
6590
|
function describeReplacement(replacement) {
|
|
5811
6591
|
if (!replacement)
|
|
5812
6592
|
return void 0;
|
|
@@ -5867,12 +6647,18 @@ var golangciRunner = {
|
|
|
5867
6647
|
const cmd = await resolveAvailableOrInstall(golangci, "golangci-lint", cwd);
|
|
5868
6648
|
if (!cmd)
|
|
5869
6649
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
5870
|
-
const result = await safeSpawnAsync(cmd, [
|
|
6650
|
+
const result = await safeSpawnAsync(cmd, [
|
|
6651
|
+
"run",
|
|
6652
|
+
"--output.json.path=stdout",
|
|
6653
|
+
...OTHER_OUTPUT_FORMATS.map((format) => `--output.${format}.path=`),
|
|
6654
|
+
"--show-stats=false",
|
|
6655
|
+
ctx.filePath
|
|
6656
|
+
], { timeout: 6e4, cwd });
|
|
5871
6657
|
const raw = (result.stdout ?? "").length > 0 ? result.stdout ?? "" : result.status !== 0 ? result.stderr || "" : "";
|
|
5872
6658
|
const parsed = parseToolRun("golangci-lint", {
|
|
5873
6659
|
result,
|
|
5874
6660
|
output: raw,
|
|
5875
|
-
// EXIT TABLE (golangci-lint
|
|
6661
|
+
// EXIT TABLE (golangci-lint v2 docs https://golangci-lint.run/docs/welcome/quick-start/; 2.14.0 exits 1 on findings and 3 on an unknown flag): 0 clean; 1 findings; 2 error; 3 error; 4 error; 5 error; other nonzero rejected.
|
|
5876
6662
|
exitCodes: { ran: [1, 2, 3, 4, 5] }
|
|
5877
6663
|
}, (raw2) => parseGolangciJson(raw2, ctx.filePath, cwd));
|
|
5878
6664
|
if (parsed.skipped)
|
|
@@ -5967,7 +6753,7 @@ var hadolint_default = hadolintRunner;
|
|
|
5967
6753
|
|
|
5968
6754
|
// dist/clients/dispatch/runners/helm-lint.js
|
|
5969
6755
|
import * as path21 from "node:path";
|
|
5970
|
-
var helm = createAvailabilityChecker("helm", ".exe");
|
|
6756
|
+
var helm = createAvailabilityChecker("helm", ".exe", ["version", "--short"]);
|
|
5971
6757
|
var inFlightByChartRoot = new PathKeyedMap(normalizeMapKey);
|
|
5972
6758
|
var HELM_LINT_TIMEOUT_MS = 3e4;
|
|
5973
6759
|
var MAX_HELM_LINT_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
@@ -5981,14 +6767,17 @@ function isWithin(root, candidate) {
|
|
|
5981
6767
|
return relative5 === "" || !relative5.startsWith(`..${path21.sep}`) && relative5 !== ".." && !path21.isAbsolute(relative5);
|
|
5982
6768
|
}
|
|
5983
6769
|
function diagnosticLocation(message, chartRoot) {
|
|
5984
|
-
const location = message.match(/(
|
|
5985
|
-
|
|
6770
|
+
const location = message.match(/(?:^|[\s(])((?:[^\s:()\r\n]*\/[^:()\r\n"]*?|[^\s:()\r\n]+)\.(?:ya?ml|tpl|json))(?::(\d+))?(?=[:\s)]|$)/i);
|
|
6771
|
+
const [, found, rawLine] = location ?? [];
|
|
6772
|
+
if (!found) {
|
|
5986
6773
|
return { filePath: path21.join(chartRoot, "Chart.yaml"), message };
|
|
5987
6774
|
}
|
|
5988
|
-
const
|
|
6775
|
+
const embedded = !message.startsWith(found);
|
|
6776
|
+
const relative5 = embedded ? found.slice(found.indexOf("/") + 1) : found;
|
|
6777
|
+
const candidate = path21.resolve(chartRoot, relative5);
|
|
5989
6778
|
return {
|
|
5990
6779
|
filePath: isWithin(chartRoot, candidate) ? candidate : path21.join(chartRoot, "Chart.yaml"),
|
|
5991
|
-
line:
|
|
6780
|
+
line: rawLine ? Number(rawLine) : void 0,
|
|
5992
6781
|
message
|
|
5993
6782
|
};
|
|
5994
6783
|
}
|
|
@@ -6103,10 +6892,10 @@ var helmLintRunner = {
|
|
|
6103
6892
|
var helm_lint_default = helmLintRunner;
|
|
6104
6893
|
|
|
6105
6894
|
// dist/clients/dispatch/runners/helm-render.js
|
|
6106
|
-
import * as
|
|
6895
|
+
import * as fs12 from "node:fs";
|
|
6107
6896
|
import * as os from "node:os";
|
|
6108
6897
|
import * as path22 from "node:path";
|
|
6109
|
-
var helm2 = createAvailabilityChecker("helm", ".exe");
|
|
6898
|
+
var helm2 = createAvailabilityChecker("helm", ".exe", ["version", "--short"]);
|
|
6110
6899
|
var trivy = createAvailabilityChecker("trivy", ".exe");
|
|
6111
6900
|
var inFlightByChartRoot2 = new PathKeyedMap(normalizeMapKey);
|
|
6112
6901
|
var RENDER_TIMEOUT_MS = 3e4;
|
|
@@ -6140,10 +6929,10 @@ function resolveTemplateSource(sourceRef, chartRoot, realChartRoot) {
|
|
|
6140
6929
|
if (!isWithin2(chartRoot, candidate))
|
|
6141
6930
|
return null;
|
|
6142
6931
|
try {
|
|
6143
|
-
if (!
|
|
6932
|
+
if (!fs12.lstatSync(candidate).isFile())
|
|
6144
6933
|
return null;
|
|
6145
|
-
const root = realChartRoot ??
|
|
6146
|
-
if (!isWithin2(root,
|
|
6934
|
+
const root = realChartRoot ?? fs12.realpathSync(chartRoot);
|
|
6935
|
+
if (!isWithin2(root, fs12.realpathSync(candidate)))
|
|
6147
6936
|
return null;
|
|
6148
6937
|
} catch {
|
|
6149
6938
|
return null;
|
|
@@ -6152,7 +6941,7 @@ function resolveTemplateSource(sourceRef, chartRoot, realChartRoot) {
|
|
|
6152
6941
|
}
|
|
6153
6942
|
function canonicalChartRoot(chartRoot) {
|
|
6154
6943
|
try {
|
|
6155
|
-
return
|
|
6944
|
+
return fs12.realpathSync(chartRoot);
|
|
6156
6945
|
} catch {
|
|
6157
6946
|
return chartRoot;
|
|
6158
6947
|
}
|
|
@@ -6387,7 +7176,7 @@ function collectRenderedFiles(root) {
|
|
|
6387
7176
|
const dir = stack.pop();
|
|
6388
7177
|
let entries;
|
|
6389
7178
|
try {
|
|
6390
|
-
entries =
|
|
7179
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
6391
7180
|
} catch {
|
|
6392
7181
|
continue;
|
|
6393
7182
|
}
|
|
@@ -6426,7 +7215,7 @@ function readRenderedTree(outputDir, chartRoot) {
|
|
|
6426
7215
|
for (const renderedPath of walk2.files) {
|
|
6427
7216
|
let content;
|
|
6428
7217
|
try {
|
|
6429
|
-
content =
|
|
7218
|
+
content = fs12.readFileSync(renderedPath, "utf-8");
|
|
6430
7219
|
} catch {
|
|
6431
7220
|
unreadable += 1;
|
|
6432
7221
|
continue;
|
|
@@ -6545,7 +7334,7 @@ function logRenderPass(filePath, chartRoot, startedAt, metadata) {
|
|
|
6545
7334
|
metadata: { chartRoot, ...metadata }
|
|
6546
7335
|
});
|
|
6547
7336
|
}
|
|
6548
|
-
function discardScratchDir(outputDir, filePath, remove = (target) =>
|
|
7337
|
+
function discardScratchDir(outputDir, filePath, remove = (target) => fs12.rmSync(target, { recursive: true, force: true })) {
|
|
6549
7338
|
try {
|
|
6550
7339
|
remove(outputDir);
|
|
6551
7340
|
} catch (error) {
|
|
@@ -6566,7 +7355,7 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
6566
7355
|
const helmCmd = await resolveAvailableOrInstall(helm2, "helm", cwd);
|
|
6567
7356
|
if (!helmCmd)
|
|
6568
7357
|
return helmUnavailableResult(cwd);
|
|
6569
|
-
const outputDir =
|
|
7358
|
+
const outputDir = fs12.mkdtempSync(path22.join(os.tmpdir(), "pi-lens-helm-render-"));
|
|
6570
7359
|
try {
|
|
6571
7360
|
const render = await safeSpawnAsync(helmCmd, ["template", "pi-lens-render", chartRoot, "--output-dir", outputDir], {
|
|
6572
7361
|
cwd,
|
|
@@ -6887,9 +7676,30 @@ function normalizeKtlintResults(parsed) {
|
|
|
6887
7676
|
}
|
|
6888
7677
|
return null;
|
|
6889
7678
|
}
|
|
7679
|
+
function parseResults(text) {
|
|
7680
|
+
try {
|
|
7681
|
+
return normalizeKtlintResults(JSON.parse(text));
|
|
7682
|
+
} catch {
|
|
7683
|
+
return null;
|
|
7684
|
+
}
|
|
7685
|
+
}
|
|
7686
|
+
function parseReporterDocument(raw) {
|
|
7687
|
+
const lines = raw.split(/\r?\n/);
|
|
7688
|
+
const start = lines.findIndex((line) => /^\s*[[{]/.test(line));
|
|
7689
|
+
if (start < 0)
|
|
7690
|
+
return parseResults(raw);
|
|
7691
|
+
for (let end = lines.length - 1; end >= start; end--) {
|
|
7692
|
+
if (!/[\]}]\s*$/.test(lines[end] ?? ""))
|
|
7693
|
+
continue;
|
|
7694
|
+
const results = parseResults(lines.slice(start, end + 1).join("\n"));
|
|
7695
|
+
if (results)
|
|
7696
|
+
return results;
|
|
7697
|
+
}
|
|
7698
|
+
return null;
|
|
7699
|
+
}
|
|
6890
7700
|
function parseKtlintOutput(raw, filePath, cwd) {
|
|
6891
7701
|
try {
|
|
6892
|
-
const parsed =
|
|
7702
|
+
const parsed = parseReporterDocument(raw);
|
|
6893
7703
|
if (!parsed)
|
|
6894
7704
|
return null;
|
|
6895
7705
|
const autofix = getAutofixCapability("ktlint");
|
|
@@ -6900,15 +7710,15 @@ function parseKtlintOutput(raw, filePath, cwd) {
|
|
|
6900
7710
|
continue;
|
|
6901
7711
|
for (const err of result.errors ?? []) {
|
|
6902
7712
|
diagnostics.push({
|
|
6903
|
-
id: `ktlint-${err.
|
|
6904
|
-
message: `[${err.
|
|
7713
|
+
id: `ktlint-${err.rule}-${err.line}-${err.column}`,
|
|
7714
|
+
message: `[${err.rule}] ${err.message}`,
|
|
6905
7715
|
filePath,
|
|
6906
7716
|
line: err.line,
|
|
6907
|
-
column: err.
|
|
7717
|
+
column: err.column,
|
|
6908
7718
|
severity: "warning",
|
|
6909
7719
|
semantic: "warning",
|
|
6910
7720
|
tool: "ktlint",
|
|
6911
|
-
rule: err.
|
|
7721
|
+
rule: err.rule,
|
|
6912
7722
|
fixable: true,
|
|
6913
7723
|
autoFixAvailable: autofix?.safePipelineAutofix ?? false,
|
|
6914
7724
|
fixKind: autofix?.fixKind === "none" ? void 0 : autofix?.fixKind
|
|
@@ -7082,16 +7892,6 @@ async function demoteInferredProjectSweepResults(results, cwd, service, signal)
|
|
|
7082
7892
|
return out;
|
|
7083
7893
|
}
|
|
7084
7894
|
|
|
7085
|
-
// dist/clients/dispatch/runners/utils.js
|
|
7086
|
-
import * as fs12 from "node:fs";
|
|
7087
|
-
function readFileContent(filePath) {
|
|
7088
|
-
try {
|
|
7089
|
-
return fs12.readFileSync(filePath, "utf-8");
|
|
7090
|
-
} catch {
|
|
7091
|
-
return void 0;
|
|
7092
|
-
}
|
|
7093
|
-
}
|
|
7094
|
-
|
|
7095
7895
|
// dist/clients/dispatch/runners/lsp.js
|
|
7096
7896
|
var LSP_SPAWN_BUDGET_MS = RUNTIME_CONFIG.pipeline.lspSpawnBudgetMs;
|
|
7097
7897
|
var LSP_DIAGNOSTICS_WAIT_MS = 2500;
|
|
@@ -7128,13 +7928,23 @@ var lspRunner = {
|
|
|
7128
7928
|
}
|
|
7129
7929
|
const lspService = getLSPService();
|
|
7130
7930
|
if (!lspService.supportsLSP(ctx.filePath)) {
|
|
7131
|
-
|
|
7931
|
+
const { disabledServerIds: disabledPrimaryServerIds } = disabledPrimaries(ctx.filePath);
|
|
7932
|
+
return {
|
|
7933
|
+
status: "skipped",
|
|
7934
|
+
diagnostics: [],
|
|
7935
|
+
semantic: "none",
|
|
7936
|
+
...disabledPrimaryServerIds.length > 0 && {
|
|
7937
|
+
primaryUnavailableCause: "disabled",
|
|
7938
|
+
disabledPrimaryServerIds
|
|
7939
|
+
}
|
|
7940
|
+
};
|
|
7132
7941
|
}
|
|
7133
7942
|
let lspDiags = [];
|
|
7134
7943
|
let serverFailed = false;
|
|
7135
7944
|
let lspClientReady = true;
|
|
7136
7945
|
let diagnosticsInconclusive = false;
|
|
7137
7946
|
let inconclusiveServerIds = [];
|
|
7947
|
+
let primaryUnavailable;
|
|
7138
7948
|
let unconfirmedServerIds = [];
|
|
7139
7949
|
let deferredServerIds = [];
|
|
7140
7950
|
let usedWarmAttach = false;
|
|
@@ -7172,6 +7982,15 @@ var lspRunner = {
|
|
|
7172
7982
|
lspDiags = touched.diags;
|
|
7173
7983
|
diagnosticsInconclusive = touched.inconclusive === true;
|
|
7174
7984
|
inconclusiveServerIds = touched.inconclusiveServerIds ?? [];
|
|
7985
|
+
if (touched.inconclusiveReason === "primary-unavailable") {
|
|
7986
|
+
const disabledPrimaryServerIds = touched.disabledPrimaryServerIds ?? [];
|
|
7987
|
+
primaryUnavailable = {
|
|
7988
|
+
primaryUnavailableCause: touched.primaryUnavailableCause ?? primaryUnavailableCause(inconclusiveServerIds, disabledPrimaryServerIds),
|
|
7989
|
+
...disabledPrimaryServerIds.length > 0 && {
|
|
7990
|
+
disabledPrimaryServerIds
|
|
7991
|
+
}
|
|
7992
|
+
};
|
|
7993
|
+
}
|
|
7175
7994
|
unconfirmedServerIds = [
|
|
7176
7995
|
.../* @__PURE__ */ new Set([
|
|
7177
7996
|
...touchCoverageGap(touched),
|
|
@@ -7223,10 +8042,20 @@ var lspRunner = {
|
|
|
7223
8042
|
};
|
|
7224
8043
|
}
|
|
7225
8044
|
if (!lspClientReady) {
|
|
7226
|
-
return {
|
|
8045
|
+
return {
|
|
8046
|
+
status: "skipped",
|
|
8047
|
+
diagnostics: [],
|
|
8048
|
+
semantic: "none",
|
|
8049
|
+
primaryUnavailableCause: "unstarted"
|
|
8050
|
+
};
|
|
7227
8051
|
}
|
|
7228
8052
|
if (diagnosticsInconclusive && lspDiags.length === 0) {
|
|
7229
|
-
return {
|
|
8053
|
+
return {
|
|
8054
|
+
status: "skipped",
|
|
8055
|
+
diagnostics: [],
|
|
8056
|
+
semantic: "none",
|
|
8057
|
+
...primaryUnavailable
|
|
8058
|
+
};
|
|
7230
8059
|
}
|
|
7231
8060
|
if (lspDiags.length === 0) {
|
|
7232
8061
|
if (deferredServerIds.length > 0) {
|
|
@@ -7291,7 +8120,15 @@ var lspRunner = {
|
|
|
7291
8120
|
}));
|
|
7292
8121
|
}
|
|
7293
8122
|
const diagnostics = convertLspDiagnostics(validLspDiags, diagnosticPath, { fixSuggestionByIndex });
|
|
7294
|
-
const
|
|
8123
|
+
const rawRangeByDiagnostic = new Map(diagnostics.map((d, i) => [d, validLspDiags[i]?.range]));
|
|
8124
|
+
const retaggedDiagnostics = retagAuxiliaryDiagnostics(diagnostics, validLspDiags, content, { cwd: ctx.cwd, fileRole: ctx.fileRole });
|
|
8125
|
+
const keptDiagnostics = [];
|
|
8126
|
+
const outOfEditScope = [];
|
|
8127
|
+
for (const d of retaggedDiagnostics) {
|
|
8128
|
+
const range = ctx.blockingOnly && d.tool === "ast-grep" && d.semantic === "blocking" ? rawRangeByDiagnostic.get(d) : void 0;
|
|
8129
|
+
const inScope = range === void 0 || spanOverlapsModifiedRanges(range.start.line + 1, (range.end?.line ?? range.start.line) + 1, ctx.modifiedRanges);
|
|
8130
|
+
(inScope ? keptDiagnostics : outOfEditScope).push(d);
|
|
8131
|
+
}
|
|
7295
8132
|
const hasErrors = keptDiagnostics.some((d) => d.semantic === "blocking");
|
|
7296
8133
|
const resultSemantic = hasErrors ? "blocking" : keptDiagnostics.length > 0 ? "warning" : "none";
|
|
7297
8134
|
return {
|
|
@@ -7306,7 +8143,8 @@ var lspRunner = {
|
|
|
7306
8143
|
},
|
|
7307
8144
|
...deferredServerIds.length > 0 && {
|
|
7308
8145
|
deferredServerIds: [...deferredServerIds]
|
|
7309
|
-
}
|
|
8146
|
+
},
|
|
8147
|
+
...outOfEditScope.length > 0 && { outOfEditScope }
|
|
7310
8148
|
};
|
|
7311
8149
|
}
|
|
7312
8150
|
};
|
|
@@ -8342,7 +9180,7 @@ var pyrightRunner = {
|
|
|
8342
9180
|
cmd = installedPath;
|
|
8343
9181
|
}
|
|
8344
9182
|
if (!cmd) {
|
|
8345
|
-
const { findCommandAsync } = await import("./chunk-
|
|
9183
|
+
const { findCommandAsync } = await import("./chunk-LLJNQKQW.js");
|
|
8346
9184
|
const foundCmd = await findCommandAsync("pyright");
|
|
8347
9185
|
if (foundCmd)
|
|
8348
9186
|
cmd = foundCmd;
|
|
@@ -8945,6 +9783,7 @@ var spotbugs_default = spotbugsRunner;
|
|
|
8945
9783
|
import * as fs15 from "node:fs";
|
|
8946
9784
|
import * as path36 from "node:path";
|
|
8947
9785
|
var shellcheck = createAvailabilityChecker("shellcheck", ".exe");
|
|
9786
|
+
var SHELLCHECK_EXIT_CODES = { ran: [1] };
|
|
8948
9787
|
var SHELLCHECK_DIALECTS = [
|
|
8949
9788
|
"sh",
|
|
8950
9789
|
"bash",
|
|
@@ -9068,7 +9907,10 @@ var shellcheckRunner = {
|
|
|
9068
9907
|
skipReason: "covered-by-primary",
|
|
9069
9908
|
// WHO claimed (#3968 F2): declared (the row's own covers, gated
|
|
9070
9909
|
// on the custom row's own command) or builtin-fact.
|
|
9071
|
-
claimSource: cover.claimSource
|
|
9910
|
+
claimSource: cover.claimSource,
|
|
9911
|
+
// #4484 round 8: the skip is a verdict only when that server's
|
|
9912
|
+
// lane answers; the dispatcher voids it otherwise.
|
|
9913
|
+
coveredBy: { runnerId: "lsp", serverId: cover.serverId }
|
|
9072
9914
|
};
|
|
9073
9915
|
}
|
|
9074
9916
|
const dialectInfo = resolveShellFileDialect(ctx.filePath);
|
|
@@ -9103,20 +9945,52 @@ var shellcheckRunner = {
|
|
|
9103
9945
|
if (result.status === 0 && !result.stdout?.trim()) {
|
|
9104
9946
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9105
9947
|
}
|
|
9106
|
-
const raw = result.stdout
|
|
9107
|
-
const
|
|
9948
|
+
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
9949
|
+
const parsed = parseToolRun("shellcheck", { result, output: raw, exitCodes: SHELLCHECK_EXIT_CODES }, (output) => parseShellcheckOutput(output, ctx.filePath, cwd));
|
|
9950
|
+
if (parsed.skipped)
|
|
9951
|
+
return parsed.skipped;
|
|
9108
9952
|
return finishParsedRun({
|
|
9109
9953
|
tool: "shellcheck",
|
|
9110
9954
|
ctx,
|
|
9111
9955
|
result,
|
|
9112
|
-
diagnostics
|
|
9956
|
+
diagnostics: parsed.diagnostics
|
|
9113
9957
|
});
|
|
9114
9958
|
}
|
|
9115
9959
|
};
|
|
9116
9960
|
var shellcheck_default = shellcheckRunner;
|
|
9117
9961
|
|
|
9118
9962
|
// dist/clients/dispatch/runners/fish-indent.js
|
|
9963
|
+
import { resolve as resolve32 } from "node:path";
|
|
9119
9964
|
var fishIndent = createAvailabilityChecker("fish_indent");
|
|
9965
|
+
var fish = createAvailabilityChecker("fish");
|
|
9966
|
+
var SYNTAX_STEP = "fish-syntax-check";
|
|
9967
|
+
function parseSyntaxErrors(output, filePath, cwd) {
|
|
9968
|
+
const diagnostics = [];
|
|
9969
|
+
for (const line of output.split("\n")) {
|
|
9970
|
+
const [, reported, lineText, message] = line.match(/^(.+) \(line (\d+)\): (.+)$/) ?? [];
|
|
9971
|
+
if (!reported || !lineText || !message)
|
|
9972
|
+
continue;
|
|
9973
|
+
const wanted = resolve32(cwd, filePath);
|
|
9974
|
+
if (!pathsEqual(resolve32(cwd, reported), wanted) && !(reported.startsWith("~/") && wanted.endsWith(reported.slice(1))))
|
|
9975
|
+
continue;
|
|
9976
|
+
const lineNumber = Number(lineText);
|
|
9977
|
+
diagnostics.push({
|
|
9978
|
+
id: `fish-syntax-${filePath}:${lineNumber}`,
|
|
9979
|
+
message: `fish: ${message.trim()}`,
|
|
9980
|
+
filePath,
|
|
9981
|
+
line: lineNumber,
|
|
9982
|
+
column: 1,
|
|
9983
|
+
severity: "error",
|
|
9984
|
+
semantic: "blocking",
|
|
9985
|
+
tool: "fish-indent",
|
|
9986
|
+
rule: "fish-syntax-error"
|
|
9987
|
+
});
|
|
9988
|
+
break;
|
|
9989
|
+
}
|
|
9990
|
+
return diagnostics;
|
|
9991
|
+
}
|
|
9992
|
+
var FISH_SYNTAX_EXIT_CODES = { ran: [127] };
|
|
9993
|
+
var BLOCKING_VERDICT = { status: "failed", semantic: "blocking" };
|
|
9120
9994
|
var fishIndentRunner = {
|
|
9121
9995
|
id: "fish-indent",
|
|
9122
9996
|
appliesTo: ["fish"],
|
|
@@ -9127,6 +10001,24 @@ var fishIndentRunner = {
|
|
|
9127
10001
|
const cmd = ctx.analysisRootMode === "adopted" ? resolveAdoptedRootCommand("fish_indent", ctx, cwd) : await fishIndent.isAvailableAsync(cwd) ? fishIndent.getCommand(cwd) : null;
|
|
9128
10002
|
if (!cmd)
|
|
9129
10003
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
10004
|
+
const fishCmd = ctx.analysisRootMode === "adopted" ? resolveAdoptedRootCommand("fish", ctx, cwd) : await fish.isAvailableAsync(cwd) ? fish.getCommand(cwd) : null;
|
|
10005
|
+
if (fishCmd) {
|
|
10006
|
+
const syntax = await safeSpawnAsync(fishCmd, ["--no-config", "--no-execute", ctx.filePath], { timeout: 1e4, cwd });
|
|
10007
|
+
const parsed = parseToolRun(SYNTAX_STEP, {
|
|
10008
|
+
result: syntax,
|
|
10009
|
+
output: syntax.stderr ?? "",
|
|
10010
|
+
exitCodes: FISH_SYNTAX_EXIT_CODES
|
|
10011
|
+
}, (output) => parseSyntaxErrors(output, ctx.filePath, cwd));
|
|
10012
|
+
if (parsed.diagnostics.length > 0) {
|
|
10013
|
+
return findingsResult(parsed.diagnostics, BLOCKING_VERDICT);
|
|
10014
|
+
}
|
|
10015
|
+
} else {
|
|
10016
|
+
recordDegradationOnce({
|
|
10017
|
+
kind: "fish-syntax-check-unavailable",
|
|
10018
|
+
subject: "fish",
|
|
10019
|
+
reason: "fish not found next to fish_indent: syntax errors are not checked"
|
|
10020
|
+
});
|
|
10021
|
+
}
|
|
9130
10022
|
const result = await safeSpawnAsync(cmd, ["--check", ctx.filePath], {
|
|
9131
10023
|
timeout: 1e4,
|
|
9132
10024
|
cwd
|
|
@@ -9134,7 +10026,12 @@ var fishIndentRunner = {
|
|
|
9134
10026
|
if (result.status === 0) {
|
|
9135
10027
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9136
10028
|
}
|
|
9137
|
-
|
|
10029
|
+
if (result.signal || result.status === null) {
|
|
10030
|
+
const didNotRun = skipUnlessToolRan("fish_indent", { result });
|
|
10031
|
+
if (didNotRun)
|
|
10032
|
+
return didNotRun;
|
|
10033
|
+
}
|
|
10034
|
+
const stderrLine = (result.stderr ?? "").split("\n").find((l) => l.trim() && !pathsEqual(resolve32(cwd, l.trim()), resolve32(cwd, ctx.filePath)));
|
|
9138
10035
|
if (stderrLine) {
|
|
9139
10036
|
const lineMatch = stderrLine.match(/\(line\s+(\d+)\)/);
|
|
9140
10037
|
const line = lineMatch ? Number(lineMatch[1]) : 1;
|
|
@@ -9151,10 +10048,7 @@ var fishIndentRunner = {
|
|
|
9151
10048
|
rule: "fish-indent-parse-error"
|
|
9152
10049
|
}
|
|
9153
10050
|
];
|
|
9154
|
-
return findingsResult(diagnostics2,
|
|
9155
|
-
status: "failed",
|
|
9156
|
-
semantic: "blocking"
|
|
9157
|
-
});
|
|
10051
|
+
return findingsResult(diagnostics2, BLOCKING_VERDICT);
|
|
9158
10052
|
}
|
|
9159
10053
|
const diagnostics = [
|
|
9160
10054
|
{
|
|
@@ -9205,6 +10099,12 @@ var shfmtRunner = {
|
|
|
9205
10099
|
timeout: 1e4,
|
|
9206
10100
|
cwd
|
|
9207
10101
|
});
|
|
10102
|
+
const didNotRun = skipUnlessToolRan("shfmt", {
|
|
10103
|
+
result,
|
|
10104
|
+
output: `${result.stdout ?? ""}${result.stderr ?? ""}`
|
|
10105
|
+
});
|
|
10106
|
+
if (didNotRun)
|
|
10107
|
+
return didNotRun;
|
|
9208
10108
|
if (result.status === 0) {
|
|
9209
10109
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9210
10110
|
}
|
|
@@ -9786,7 +10686,10 @@ var taploRunner = {
|
|
|
9786
10686
|
// an unexplained empty output on the delivery surfaces
|
|
9787
10687
|
// (defect shape 10). F2 adds the claim's provenance beside it.
|
|
9788
10688
|
skipReason: "covered-by-primary",
|
|
9789
|
-
claimSource: cover.claimSource
|
|
10689
|
+
claimSource: cover.claimSource,
|
|
10690
|
+
// #4484 round 8: the skip is a verdict only when that server's
|
|
10691
|
+
// lane answers; the dispatcher voids it otherwise.
|
|
10692
|
+
coveredBy: { runnerId: "lsp", serverId: cover.serverId }
|
|
9790
10693
|
};
|
|
9791
10694
|
}
|
|
9792
10695
|
let cmd = localBinPath(findLocalBinUpwards("taplo", cwd)) ?? null;
|
|
@@ -10634,11 +11537,6 @@ function defaultFixSuggestion2(defectClass, ruleId) {
|
|
|
10634
11537
|
}
|
|
10635
11538
|
return "Refactor this pattern to a safer, explicit form matching project conventions.";
|
|
10636
11539
|
}
|
|
10637
|
-
function isLineInModifiedRanges(line, ranges) {
|
|
10638
|
-
if (!ranges || ranges.length === 0)
|
|
10639
|
-
return true;
|
|
10640
|
-
return ranges.some((r) => line >= r.start && line <= r.end);
|
|
10641
|
-
}
|
|
10642
11540
|
function getTotalLinesChanged(ranges) {
|
|
10643
11541
|
if (!ranges || ranges.length === 0)
|
|
10644
11542
|
return 0;
|
|
@@ -10763,19 +11661,20 @@ var treeSitterRunner = {
|
|
|
10763
11661
|
const contentFromFacts = ctx.facts.getFileFact(filePath, "file.content");
|
|
10764
11662
|
const contentOverride = contentFromFacts !== void 0 && contentFromFacts !== null ? contentFromFacts : void 0;
|
|
10765
11663
|
const diagnostics = [];
|
|
11664
|
+
const withheld = [];
|
|
11665
|
+
let queryRunFailed = false;
|
|
10766
11666
|
try {
|
|
10767
11667
|
const found = await client.runQueriesOnFile(effectiveQueries, filePath, languageId, { maxResults: 10 }, contentOverride);
|
|
10768
11668
|
for (const { queryDef: query, match } of found) {
|
|
10769
11669
|
const { line, column } = match;
|
|
10770
11670
|
const isSeverityBlocking = query.severity === "error" || query.inline_tier === "blocking" || SILENT_ERROR_QUERY_IDS.has(query.id);
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
}
|
|
11671
|
+
const endLine = line + (match.matchedText.match(/\n/g)?.length ?? 0);
|
|
11672
|
+
const outOfScope = ctx.blockingOnly && isSeverityBlocking && !spanOverlapsModifiedRanges(line, endLine, ctx.modifiedRanges);
|
|
10774
11673
|
const semantic = query.severity === "error" ? "blocking" : query.severity === "warning" ? "warning" : "none";
|
|
10775
11674
|
const defectClass = query.defect_class ?? classifyDefect(query.id, "tree-sitter", query.message);
|
|
10776
11675
|
const suggestion = query.has_fix && query.fix_action ? `${query.fix_action} this statement` : semantic === "blocking" ? defaultFixSuggestion2(defectClass, query.id) : void 0;
|
|
10777
11676
|
const hasSuggestedFix = !!query.has_fix;
|
|
10778
|
-
diagnostics.push({
|
|
11677
|
+
(outOfScope ? withheld : diagnostics).push({
|
|
10779
11678
|
id: `tree-sitter:${query.id}:${line}`,
|
|
10780
11679
|
message: query.message.replace(/\{\{(\w+)\}\}/g, (_, name) => match.captures[name]?.trim() ?? `{{${name}}}`),
|
|
10781
11680
|
filePath,
|
|
@@ -10797,6 +11696,7 @@ var treeSitterRunner = {
|
|
|
10797
11696
|
});
|
|
10798
11697
|
}
|
|
10799
11698
|
} catch (err) {
|
|
11699
|
+
queryRunFailed = true;
|
|
10800
11700
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10801
11701
|
if (classifyTreeSitterWasmError(err) === "abort") {
|
|
10802
11702
|
markTreeSitterWasmAborted();
|
|
@@ -10856,6 +11756,10 @@ var treeSitterRunner = {
|
|
|
10856
11756
|
} catch {
|
|
10857
11757
|
}
|
|
10858
11758
|
}
|
|
11759
|
+
const observationExtras = {
|
|
11760
|
+
...withheld.length > 0 && { outOfEditScope: withheld },
|
|
11761
|
+
...queryRunFailed && { inconclusive: true }
|
|
11762
|
+
};
|
|
10859
11763
|
if (diagnostics.length === 0) {
|
|
10860
11764
|
if (!isTreeSitterWasmAborted() && !client.getLanguage(languageId)) {
|
|
10861
11765
|
logTreeSitter({
|
|
@@ -10865,7 +11769,11 @@ var treeSitterRunner = {
|
|
|
10865
11769
|
reason: "grammar_unavailable",
|
|
10866
11770
|
status: "skipped"
|
|
10867
11771
|
});
|
|
10868
|
-
return {
|
|
11772
|
+
return {
|
|
11773
|
+
status: "skipped",
|
|
11774
|
+
diagnostics: [],
|
|
11775
|
+
semantic: "none"
|
|
11776
|
+
};
|
|
10869
11777
|
}
|
|
10870
11778
|
logTreeSitter({
|
|
10871
11779
|
phase: "runner_complete",
|
|
@@ -10877,7 +11785,12 @@ var treeSitterRunner = {
|
|
|
10877
11785
|
queryCount: languageQueries.length,
|
|
10878
11786
|
effectiveQueryCount: effectiveQueries.length
|
|
10879
11787
|
});
|
|
10880
|
-
return {
|
|
11788
|
+
return {
|
|
11789
|
+
status: "succeeded",
|
|
11790
|
+
diagnostics: [],
|
|
11791
|
+
semantic: "none",
|
|
11792
|
+
...observationExtras
|
|
11793
|
+
};
|
|
10881
11794
|
}
|
|
10882
11795
|
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
|
|
10883
11796
|
const blockingCount = diagnostics.filter((d) => d.semantic === "blocking").length;
|
|
@@ -10891,10 +11804,13 @@ var treeSitterRunner = {
|
|
|
10891
11804
|
queryCount: languageQueries.length,
|
|
10892
11805
|
effectiveQueryCount: effectiveQueries.length
|
|
10893
11806
|
});
|
|
10894
|
-
return
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
11807
|
+
return {
|
|
11808
|
+
...findingsResult(diagnostics, {
|
|
11809
|
+
status: hasBlocking ? "failed" : "succeeded",
|
|
11810
|
+
semantic: hasBlocking ? "blocking" : "warning"
|
|
11811
|
+
}),
|
|
11812
|
+
...observationExtras
|
|
11813
|
+
};
|
|
10898
11814
|
}
|
|
10899
11815
|
};
|
|
10900
11816
|
var tree_sitter_default = treeSitterRunner;
|
|
@@ -11305,8 +12221,6 @@ function isTestSuiteOrganizer(calls) {
|
|
|
11305
12221
|
// dist/clients/dispatch/rules/high-complexity.js
|
|
11306
12222
|
var DEFAULT_HIGH_COMPLEXITY_THRESHOLD = 15;
|
|
11307
12223
|
var DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD = 6;
|
|
11308
|
-
var ccThreshold = DEFAULT_HIGH_COMPLEXITY_THRESHOLD;
|
|
11309
|
-
var depthThreshold = DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD;
|
|
11310
12224
|
var highComplexityRule = {
|
|
11311
12225
|
id: "high-complexity",
|
|
11312
12226
|
requires: ["file.functionSummaries"],
|
|
@@ -11317,12 +12231,12 @@ var highComplexityRule = {
|
|
|
11317
12231
|
const fns = store.getFileFact(ctx.filePath, "file.functionSummaries") ?? [];
|
|
11318
12232
|
const diagnostics = [];
|
|
11319
12233
|
const configuredCcThreshold = ctx.projectConfig?.rules["high-complexity"]?.threshold;
|
|
11320
|
-
const activeCcThreshold = configuredCcThreshold ??
|
|
12234
|
+
const activeCcThreshold = configuredCcThreshold ?? DEFAULT_HIGH_COMPLEXITY_THRESHOLD;
|
|
11321
12235
|
for (const f of fns) {
|
|
11322
12236
|
if (isTestSuiteOrganizer(f.outgoingCalls))
|
|
11323
12237
|
continue;
|
|
11324
12238
|
const ccBreached = f.cyclomaticComplexity >= activeCcThreshold;
|
|
11325
|
-
const depthBreached = f.maxNestingDepth >=
|
|
12239
|
+
const depthBreached = f.maxNestingDepth >= DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD;
|
|
11326
12240
|
if (!ccBreached && !depthBreached)
|
|
11327
12241
|
continue;
|
|
11328
12242
|
const parts = [];
|
|
@@ -11348,7 +12262,6 @@ var highComplexityRule = {
|
|
|
11348
12262
|
|
|
11349
12263
|
// dist/clients/dispatch/rules/high-fan-out.js
|
|
11350
12264
|
var DEFAULT_HIGH_FAN_OUT_THRESHOLD = 20;
|
|
11351
|
-
var fanOutThreshold = DEFAULT_HIGH_FAN_OUT_THRESHOLD;
|
|
11352
12265
|
var highFanOutRule = {
|
|
11353
12266
|
id: "high-fan-out",
|
|
11354
12267
|
requires: ["file.functionSummaries"],
|
|
@@ -11359,7 +12272,7 @@ var highFanOutRule = {
|
|
|
11359
12272
|
const fns = store.getFileFact(ctx.filePath, "file.functionSummaries") ?? [];
|
|
11360
12273
|
const diagnostics = [];
|
|
11361
12274
|
const configuredFanOutThreshold = ctx.projectConfig?.rules["high-fan-out"]?.threshold;
|
|
11362
|
-
const activeFanOutThreshold = configuredFanOutThreshold ??
|
|
12275
|
+
const activeFanOutThreshold = configuredFanOutThreshold ?? DEFAULT_HIGH_FAN_OUT_THRESHOLD;
|
|
11363
12276
|
for (const f of fns) {
|
|
11364
12277
|
if (isTestSuiteOrganizer(f.outgoingCalls))
|
|
11365
12278
|
continue;
|
|
@@ -11718,6 +12631,8 @@ function applyProjectLensConfig(cwd) {
|
|
|
11718
12631
|
return loadPiLensProjectConfig(cwd);
|
|
11719
12632
|
}
|
|
11720
12633
|
var sessionFacts = new FactStore("dispatch");
|
|
12634
|
+
var preEditCaptureFacts = new FactStore("pre-edit-capture");
|
|
12635
|
+
var preEditCapturesInFlight = /* @__PURE__ */ new Map();
|
|
11721
12636
|
setFactStoreEvictionReporter((subject, axis, reason) => {
|
|
11722
12637
|
if (axis === "pinned-over-budget") {
|
|
11723
12638
|
recordDegradationOnce({
|
|
@@ -11899,12 +12814,16 @@ function resetDispatchBaselines(cwd) {
|
|
|
11899
12814
|
resetAstGrepNapiLoadState();
|
|
11900
12815
|
resetTreeSitterClientLoadState();
|
|
11901
12816
|
sessionFacts.clearAll();
|
|
12817
|
+
for (const controller of preEditCapturesInFlight.values())
|
|
12818
|
+
controller.abort();
|
|
12819
|
+
preEditCaptureFacts.clearAll();
|
|
11902
12820
|
resetSessionSlopScore();
|
|
11903
12821
|
clearCoverageNoticeState();
|
|
11904
12822
|
clearReviewGraphWorkspaceCache();
|
|
11905
12823
|
clearReverseDepsIndexCache();
|
|
11906
12824
|
clearModuleGraphCache();
|
|
11907
|
-
|
|
12825
|
+
resetCascadeUnansweredPrimariesDelivered();
|
|
12826
|
+
resetCascadePendingNeighbors();
|
|
11908
12827
|
primaryFilesThisTurn.clear();
|
|
11909
12828
|
cascadeSessionStats = {
|
|
11910
12829
|
runs: 0,
|
|
@@ -11920,7 +12839,6 @@ var cascadeSessionStats = {
|
|
|
11920
12839
|
diagnosticsSurfaced: 0,
|
|
11921
12840
|
coldSnapshotTouches: 0
|
|
11922
12841
|
};
|
|
11923
|
-
var recentlyCleanNeighborCache = /* @__PURE__ */ new Map();
|
|
11924
12842
|
var primaryFilesThisTurn = /* @__PURE__ */ new Set();
|
|
11925
12843
|
var MAX_PER_FILE = RUNTIME_CONFIG.pipeline.cascadeMaxDiagnosticsPerFile;
|
|
11926
12844
|
var MAX_FILES = RUNTIME_CONFIG.pipeline.cascadeMaxFiles;
|
|
@@ -11948,8 +12866,16 @@ var CASCADE_GRAPH_KINDS = /* @__PURE__ */ new Set([
|
|
|
11948
12866
|
"ruby",
|
|
11949
12867
|
"cxx"
|
|
11950
12868
|
]);
|
|
12869
|
+
var IMPLICIT_SCOPE_NEIGHBOR_CAP = MAX_FILES * 2;
|
|
11951
12870
|
async function dispatchLintWithResult(filePath, cwd, pi, modifiedRanges, logContext, options) {
|
|
11952
|
-
const
|
|
12871
|
+
const created = createDispatchContext(filePath, cwd, pi, sessionFacts, options?.blockingOnly ?? true, modifiedRanges, options?.projectRoot, options?.writeIndex, options?.telemetryModel, options?.telemetryProvider, options?.sessionGeneration, options?.sessionId, options?.analysisRootMode);
|
|
12872
|
+
const ctx = options?.owedRanges?.size || options?.recordedRunnerIds?.size ? {
|
|
12873
|
+
...created,
|
|
12874
|
+
...options.owedRanges?.size && { owedRanges: options.owedRanges },
|
|
12875
|
+
...options.recordedRunnerIds?.size && {
|
|
12876
|
+
recordedRunnerIds: options.recordedRunnerIds
|
|
12877
|
+
}
|
|
12878
|
+
} : created;
|
|
11953
12879
|
sessionFacts.clearFileFactsFor(ctx.filePath);
|
|
11954
12880
|
try {
|
|
11955
12881
|
const kind = ctx.kind;
|
|
@@ -12080,14 +13006,17 @@ function enforceWarmWordIndexLruCap() {
|
|
|
12080
13006
|
return;
|
|
12081
13007
|
}
|
|
12082
13008
|
}
|
|
13009
|
+
function usableWarmWordIndex(index) {
|
|
13010
|
+
return index?.forward ? index : void 0;
|
|
13011
|
+
}
|
|
12083
13012
|
function acquireWarmWordIndex(cwd) {
|
|
12084
13013
|
const key2 = path50.resolve(cwd);
|
|
12085
13014
|
let entry = warmWordIndexes.get(key2);
|
|
12086
13015
|
if (!entry) {
|
|
12087
13016
|
const snapshot = loadProjectSnapshot(key2);
|
|
12088
|
-
const index = deserializeWordIndex(snapshot?.wordIndex) ?? void 0;
|
|
13017
|
+
const index = usableWarmWordIndex(deserializeWordIndex(snapshot?.wordIndex) ?? void 0);
|
|
12089
13018
|
entry = {
|
|
12090
|
-
index
|
|
13019
|
+
index,
|
|
12091
13020
|
timer: void 0,
|
|
12092
13021
|
leases: 0,
|
|
12093
13022
|
lastUsedAt: Date.now(),
|
|
@@ -12115,6 +13044,26 @@ function acquireWarmWordIndex(cwd) {
|
|
|
12115
13044
|
}
|
|
12116
13045
|
};
|
|
12117
13046
|
}
|
|
13047
|
+
function adoptPublishedWarmWordIndex(cwd, published, trigger) {
|
|
13048
|
+
const index = usableWarmWordIndex(published);
|
|
13049
|
+
if (!index)
|
|
13050
|
+
return;
|
|
13051
|
+
const key2 = path50.resolve(cwd);
|
|
13052
|
+
const entry = warmWordIndexes.get(key2);
|
|
13053
|
+
if (!entry || entry.index)
|
|
13054
|
+
return;
|
|
13055
|
+
entry.index = index;
|
|
13056
|
+
entry.lastUsedAt = Date.now();
|
|
13057
|
+
scheduleWarmWordIndexIdleEviction(key2, entry);
|
|
13058
|
+
logWordIndex({
|
|
13059
|
+
phase: "warm_cache_adopted",
|
|
13060
|
+
cwd: key2,
|
|
13061
|
+
trigger,
|
|
13062
|
+
indexedFileCount: index.docCount,
|
|
13063
|
+
tokens: index.postings.size
|
|
13064
|
+
});
|
|
13065
|
+
}
|
|
13066
|
+
setWordIndexPublishedListener(adoptPublishedWarmWordIndex);
|
|
12118
13067
|
function _resetWarmWordIndexCacheForTests() {
|
|
12119
13068
|
for (const entry of warmWordIndexes.values())
|
|
12120
13069
|
clearWarmWordIndexTimer(entry);
|
|
@@ -12177,7 +13126,13 @@ async function warmLspForFile(absPath, host) {
|
|
|
12177
13126
|
clientScope: "primary",
|
|
12178
13127
|
maxClientWaitMs: WARMUP_CLIENT_WAIT_MS,
|
|
12179
13128
|
maxDiagnosticsWaitMs: WARMUP_DIAGNOSTICS_WAIT_MS,
|
|
12180
|
-
source: "mcp-warmup"
|
|
13129
|
+
source: "mcp-warmup",
|
|
13130
|
+
// #3405: every caller of `analyzeFile` (the MCP hosts' post-write hooks,
|
|
13131
|
+
// warm and cold, and `pilens_analyze`) asks about the bytes on disk now,
|
|
13132
|
+
// and this is the analysis's first push of them, so it is the save. A
|
|
13133
|
+
// save-triggered server (Expert compiles on didSave and on nothing else)
|
|
13134
|
+
// answers an MCP host's edit only because of it.
|
|
13135
|
+
saved: true
|
|
12181
13136
|
});
|
|
12182
13137
|
} catch {
|
|
12183
13138
|
}
|
|
@@ -12298,6 +13253,18 @@ export {
|
|
|
12298
13253
|
CacheManager,
|
|
12299
13254
|
getDiagnosticTracker,
|
|
12300
13255
|
normalizeRuleId,
|
|
13256
|
+
readFileContent,
|
|
13257
|
+
applyRulePolicy,
|
|
13258
|
+
convertLspDiagnostics,
|
|
13259
|
+
applyFindingPolicy,
|
|
13260
|
+
loadProjectRulePolicyMap,
|
|
13261
|
+
inlineBlockerIdentities,
|
|
13262
|
+
applyPushedFindingPolicy,
|
|
13263
|
+
applyPushedFindingPolicyByFile,
|
|
13264
|
+
applyLspFindingPolicy,
|
|
13265
|
+
filterFindingsByDisposition,
|
|
13266
|
+
stampLineHashes,
|
|
13267
|
+
owedByContentOnly,
|
|
12301
13268
|
getToolPlan,
|
|
12302
13269
|
resetObservedRunnerLatency,
|
|
12303
13270
|
requeueRunnerFindings,
|
|
@@ -12305,25 +13272,28 @@ export {
|
|
|
12305
13272
|
dropStaleRunnerFindings,
|
|
12306
13273
|
resetPendingRunnerFindings,
|
|
12307
13274
|
pendingRunnerFindingsSize,
|
|
12308
|
-
|
|
13275
|
+
laneCopyStandsFor,
|
|
12309
13276
|
DELTA_UNUSED_PROMOTION_NOTE,
|
|
12310
13277
|
formatDiagnostics,
|
|
12311
13278
|
createDispatchContext,
|
|
12312
13279
|
getLatencyReports,
|
|
12313
13280
|
cascadeSettleWaitMs,
|
|
12314
|
-
convertLspDiagnostics,
|
|
12315
|
-
applyFindingPolicy,
|
|
12316
|
-
loadProjectRulePolicyMap,
|
|
12317
|
-
inlineBlockerIdentities,
|
|
12318
|
-
applyPushedFindingPolicy,
|
|
12319
|
-
applyLspFindingPolicy,
|
|
12320
|
-
filterFindingsByDisposition,
|
|
12321
13281
|
markUnreconciledFindings,
|
|
12322
13282
|
formatCacheAgeLabel,
|
|
13283
|
+
dispositionSuppressedLine,
|
|
12323
13284
|
admitsProjectWideFindings,
|
|
13285
|
+
formatCascadeNeighborDiagnostics,
|
|
13286
|
+
composeCascadeSection,
|
|
12324
13287
|
cascadeCarrySuffix,
|
|
13288
|
+
markCascadeUnansweredPrimariesDelivered,
|
|
13289
|
+
renderCascadeResult,
|
|
13290
|
+
cascadeStillPresentSince,
|
|
13291
|
+
recordDeliveredCascadeNeighbor,
|
|
13292
|
+
forgetCascadePendingNeighbor,
|
|
13293
|
+
listCascadePendingNeighbors,
|
|
12325
13294
|
logCascade,
|
|
12326
13295
|
resetCascadeTierSessionState,
|
|
13296
|
+
peekOutstandingCascadeTouches,
|
|
12327
13297
|
loadSg,
|
|
12328
13298
|
canHandle,
|
|
12329
13299
|
getLang,
|