pi-lens 4.4.2 → 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 +306 -0
- package/README.md +13 -1
- package/dist/{chunk-VITUCP5A.js → chunk-24AKHFGP.js} +9 -7
- package/dist/{chunk-JSQFTSC6.js → chunk-2FN63LPV.js} +11 -11
- package/dist/{chunk-CF24OIYI.js → chunk-2KXTHF3M.js} +20 -20
- package/dist/{chunk-ESBQHFMJ.js → chunk-3DA2JDOL.js} +543 -349
- 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-XKIZ2HNN.js → chunk-5IUSNGOC.js} +18 -16
- package/dist/{chunk-EJIUXPBX.js → chunk-5OFV52AM.js} +1 -1
- package/dist/{chunk-AW7R2GWG.js → chunk-5VSF4UUQ.js} +12 -7
- package/dist/{chunk-NW7BOILN.js → chunk-5WRPDP2A.js} +18 -18
- package/dist/{chunk-7ULNCDCO.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-ODBNXWT4.js → chunk-CT4MN5IU.js} +1271 -262
- package/dist/{chunk-34WSVGEM.js → chunk-CUHSHSB6.js} +83 -5
- 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-ED36RF6Y.js +17 -0
- package/dist/{chunk-76MWC2K6.js → chunk-EUXZEFTV.js} +90 -97
- package/dist/{chunk-QOZXJ4NA.js → chunk-FM4RDMKT.js} +11 -8
- package/dist/{chunk-66VMUL7Q.js → chunk-GAQ7OQG6.js} +31 -28
- package/dist/{chunk-Q6ZWTCLY.js → chunk-GL5LUMZE.js} +23 -24
- package/dist/{chunk-BKE7E7TC.js → chunk-GMX5OS7B.js} +9 -9
- package/dist/{chunk-ZHFZWTZV.js → chunk-GSLNCYGG.js} +11 -11
- package/dist/{chunk-ARJ6PLFH.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-GZYBXISR.js → chunk-IUE7SSKV.js} +9 -9
- 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-IBRALRBR.js → chunk-JW3YWBVB.js} +15 -14
- 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-WOKKRCJ5.js → chunk-MBKQHGA7.js} +15 -14
- package/dist/{chunk-P7266HLM.js → chunk-MPNJLASA.js} +2 -2
- package/dist/{chunk-6GFRNVYR.js → chunk-MZGQNL3Y.js} +10 -10
- package/dist/{chunk-QZVW3AAK.js → chunk-N5FLEO7W.js} +33 -31
- package/dist/{chunk-3JNKMP3B.js → chunk-O4NWQT6I.js} +4 -4
- package/dist/{chunk-PFNSLWU5.js → chunk-OHKJ7PQF.js} +33 -31
- 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-3UUPUE3O.js → chunk-R3T7CLQ2.js} +84 -60
- package/dist/{chunk-23WOO7TX.js → chunk-R7YOCSNV.js} +10 -10
- package/dist/{chunk-2CD5RS6M.js → chunk-RKBXZN3A.js} +23 -2
- package/dist/{chunk-OG5UUPN7.js → chunk-RKKOYPRA.js} +14 -14
- package/dist/{chunk-52FUZI6K.js → chunk-RMLC67LF.js} +1 -1
- package/dist/{chunk-XMSXXAHW.js → chunk-ROYSX2S5.js} +2 -2
- package/dist/{chunk-PV6LR5P5.js → chunk-RVK72CZX.js} +9605 -14776
- package/dist/{chunk-FLKWCIZH.js → chunk-S2HEXIWI.js} +5 -5
- package/dist/{chunk-UZ3TUTRV.js → chunk-S67KYG37.js} +1 -1
- package/dist/{chunk-JWA5I3SR.js → chunk-SD4I7ZO4.js} +16 -18
- 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-IXXDFY73.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-EETY4LF7.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-XHJBS436.js +4217 -0
- 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-2ZGIZPDG.js → chunk-YCWYO6TQ.js} +41 -38
- package/dist/{chunk-66SXUJCA.js → chunk-YH5MVY2U.js} +10 -8
- package/dist/{chunk-AOHZU2BM.js → chunk-YNE3RP52.js} +1 -1
- package/dist/{chunk-GOYRYZ2R.js → chunk-ZHH37KZL.js} +72 -20
- package/dist/{chunk-ZGDGW2V3.js → chunk-ZIVJBOO3.js} +2 -2
- package/dist/{chunk-GHB6AYCP.js → chunk-ZVUL7QYY.js} +29 -28
- package/dist/index.js +11559 -6213
- package/dist/mcp/analyze-cli.js +10 -9
- package/dist/mcp/cli.js +41 -38
- package/dist/mcp/server.js +1142 -495
- package/dist/mcp/worker.js +61 -57
- 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 +109 -11
- package/docs/pi-lens-monitor.md +8 -2
- package/docs/pi-lens-retro.md +4 -1
- package/docs/pi-lens-reviewer.md +114 -3
- package/docs/pi-lens-subagent.md +27 -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-3WA4HP4I.js +0 -55
- package/dist/chunk-466Z26MG.js +0 -30
- package/dist/chunk-5JM2524W.js +0 -84
- package/dist/chunk-CO2G5PHH.js +0 -84
- package/dist/chunk-LOP6GRPH.js +0 -31
- package/dist/chunk-UOPVJQ4N.js +0 -103
- package/dist/chunk-XPZPXCBV.js +0 -28
- /package/dist/{chunk-FC4RP4I2.js → chunk-6HWVI6MI.js} +0 -0
|
@@ -2,17 +2,7 @@ import { createRequire as __pilensCreateRequire } from "node:module"; const requ
|
|
|
2
2
|
import {
|
|
3
3
|
getLazyInstallAttempt,
|
|
4
4
|
tryLazyInstall
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import {
|
|
7
|
-
stripAnsi
|
|
8
|
-
} from "./chunk-FC4RP4I2.js";
|
|
9
|
-
import {
|
|
10
|
-
isTrivyEnabled,
|
|
11
|
-
resolveSeverityFloor
|
|
12
|
-
} from "./chunk-66SXUJCA.js";
|
|
13
|
-
import {
|
|
14
|
-
rustClient
|
|
15
|
-
} from "./chunk-MRXKYPCS.js";
|
|
5
|
+
} from "./chunk-UBOQLVT2.js";
|
|
16
6
|
import {
|
|
17
7
|
findingsResult,
|
|
18
8
|
finishParsedRun,
|
|
@@ -21,11 +11,29 @@ import {
|
|
|
21
11
|
isRunnerClaimSource,
|
|
22
12
|
isRunnerSkipReason,
|
|
23
13
|
parseToolRun,
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
reachedNoVerdict,
|
|
15
|
+
skipUnlessToolRan,
|
|
16
|
+
spanOverlapsModifiedRanges
|
|
17
|
+
} from "./chunk-RKBXZN3A.js";
|
|
18
|
+
import {
|
|
19
|
+
stripAnsi
|
|
20
|
+
} from "./chunk-6HWVI6MI.js";
|
|
26
21
|
import {
|
|
27
22
|
spawnFailedWithNoOutput
|
|
28
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-S67KYG37.js";
|
|
24
|
+
import {
|
|
25
|
+
computeImpactCascade
|
|
26
|
+
} from "./chunk-KN35K52N.js";
|
|
27
|
+
import {
|
|
28
|
+
goClient
|
|
29
|
+
} from "./chunk-ROYSX2S5.js";
|
|
30
|
+
import {
|
|
31
|
+
isTrivyEnabled,
|
|
32
|
+
resolveSeverityFloor
|
|
33
|
+
} from "./chunk-YH5MVY2U.js";
|
|
34
|
+
import {
|
|
35
|
+
rustClient
|
|
36
|
+
} from "./chunk-EBC36LNN.js";
|
|
29
37
|
import {
|
|
30
38
|
coveringLaneAvailable,
|
|
31
39
|
createAvailabilityChecker,
|
|
@@ -33,6 +41,7 @@ import {
|
|
|
33
41
|
getDispatchAvailabilityGeneration,
|
|
34
42
|
lspPrimaryCoversFile,
|
|
35
43
|
recordAvailabilityProbeOverrun,
|
|
44
|
+
resolveAdoptedRootCommand,
|
|
36
45
|
resolveAvailableOrInstall,
|
|
37
46
|
resolveCommandArgsWithInstallFallback,
|
|
38
47
|
resolveLocalFirstAsync,
|
|
@@ -40,7 +49,7 @@ import {
|
|
|
40
49
|
resolveToolCommand,
|
|
41
50
|
resolveToolCommandWithInstallFallback,
|
|
42
51
|
resolveVendorToolCommand
|
|
43
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-ZHH37KZL.js";
|
|
44
53
|
import {
|
|
45
54
|
biomeConfigArgs,
|
|
46
55
|
findCompiledClassesDir,
|
|
@@ -59,47 +68,44 @@ import {
|
|
|
59
68
|
hasYamllintConfig,
|
|
60
69
|
markdownlintConfigArgs,
|
|
61
70
|
ruffConfigArgs
|
|
62
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-Y6GZHWSJ.js";
|
|
63
72
|
import {
|
|
64
73
|
importFactProvider
|
|
65
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-IYNJ6YPZ.js";
|
|
66
75
|
import {
|
|
67
76
|
functionFactProvider
|
|
68
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-EUXZEFTV.js";
|
|
69
78
|
import {
|
|
70
79
|
extractFactsFromTree
|
|
71
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-T57LYLZT.js";
|
|
72
81
|
import {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} from "./chunk-XMSXXAHW.js";
|
|
82
|
+
buildOrUpdateGraph,
|
|
83
|
+
clearReviewGraphWorkspaceCache,
|
|
84
|
+
fileContentProvider
|
|
85
|
+
} from "./chunk-XHJBS436.js";
|
|
78
86
|
import {
|
|
79
87
|
MAX_BLOCKING_RULE_COMPLEXITY,
|
|
80
|
-
|
|
88
|
+
PRIMARY_UNAVAILABLE_CAUSE,
|
|
81
89
|
applyDispositions,
|
|
82
90
|
applyDispositionsMultiFile,
|
|
83
91
|
buildEffectiveAstGrepCatalog,
|
|
84
|
-
buildOrUpdateGraph,
|
|
85
92
|
calculateRuleComplexity,
|
|
86
93
|
classifyDefect,
|
|
87
94
|
classifyDiagnostic,
|
|
88
95
|
classifyDiagnosticTier,
|
|
89
96
|
clearPendingAuxiliaryCoverage,
|
|
90
|
-
|
|
97
|
+
combinePrimaryUnavailableCauses,
|
|
91
98
|
enabledAuxiliaryLspServerIds,
|
|
92
|
-
exceedsLspSyncLimits,
|
|
93
99
|
fetchTsserverProjectIdentity,
|
|
94
|
-
fileContentProvider,
|
|
95
100
|
getLSPService,
|
|
96
|
-
getRunnerTimeoutFloorMs,
|
|
97
101
|
hasAnyDispositionMarks,
|
|
98
102
|
hasAuxiliaryLspPublishedForRoot,
|
|
99
103
|
hasPendingAuxiliaryCoverage,
|
|
100
104
|
isOverlyBroadPattern,
|
|
101
105
|
isRuleIgnoredForPath,
|
|
102
106
|
isStructuredRule,
|
|
107
|
+
lineContentHash,
|
|
108
|
+
primaryUnavailableCause,
|
|
103
109
|
recordDiagnostics,
|
|
104
110
|
recordNapiFallbackCoverage,
|
|
105
111
|
recordRunner,
|
|
@@ -107,24 +113,40 @@ import {
|
|
|
107
113
|
touchCoverageGap,
|
|
108
114
|
tryWarmAttachedCodeActions,
|
|
109
115
|
tryWarmAttachedDiagnostics
|
|
110
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-RVK72CZX.js";
|
|
117
|
+
import {
|
|
118
|
+
ANY_POSITION,
|
|
119
|
+
retainRecordedFindings
|
|
120
|
+
} from "./chunk-IWDLU6K3.js";
|
|
111
121
|
import {
|
|
112
122
|
mapWithConcurrency
|
|
113
123
|
} from "./chunk-XIMYZ3JA.js";
|
|
114
124
|
import {
|
|
115
125
|
LSP_SERVERS,
|
|
126
|
+
disabledPrimaries,
|
|
116
127
|
getAstGrepRuleSources,
|
|
117
|
-
registerRunnerId
|
|
118
|
-
|
|
128
|
+
registerRunnerId,
|
|
129
|
+
resolveAnalysisRoot
|
|
130
|
+
} from "./chunk-3DA2JDOL.js";
|
|
119
131
|
import {
|
|
120
132
|
augmentPythonEnvironment,
|
|
121
133
|
detectPythonEnvironment
|
|
122
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-CUHSHSB6.js";
|
|
123
135
|
import {
|
|
124
136
|
loadProjectSnapshot,
|
|
125
137
|
readJsonCache,
|
|
126
138
|
readJsonCacheAsync
|
|
127
|
-
} 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";
|
|
128
150
|
import {
|
|
129
151
|
BUNDLED_QUERIES_ROOT,
|
|
130
152
|
classifyTreeSitterWasmError,
|
|
@@ -144,44 +166,44 @@ import {
|
|
|
144
166
|
ruleFilesForLanguage,
|
|
145
167
|
ruleSourceLanguages,
|
|
146
168
|
walk
|
|
147
|
-
} from "./chunk-
|
|
148
|
-
import {
|
|
149
|
-
buildModuleGraph,
|
|
150
|
-
clearModuleGraphCache
|
|
151
|
-
} from "./chunk-GBPP5P7X.js";
|
|
169
|
+
} from "./chunk-US7ECLD7.js";
|
|
152
170
|
import {
|
|
153
171
|
WORD_INDEX_MAX_BYTES,
|
|
154
172
|
deserializeWordIndex,
|
|
155
173
|
logWordIndex,
|
|
156
174
|
removeWordIndexDocumentAsync,
|
|
157
175
|
scheduleWordIndexPersist,
|
|
176
|
+
setWordIndexPublishedListener,
|
|
158
177
|
updateWordIndexDocumentForEdit
|
|
159
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-W66O5E25.js";
|
|
160
179
|
import {
|
|
161
180
|
PathKeyedMap
|
|
162
181
|
} from "./chunk-Z3CCVDUB.js";
|
|
163
182
|
import {
|
|
164
183
|
WARM_CODE_ACTION_LOOKUP_LIMIT,
|
|
165
|
-
contentHash
|
|
166
|
-
|
|
167
|
-
|
|
184
|
+
contentHash
|
|
185
|
+
} from "./chunk-KAPJINKN.js";
|
|
186
|
+
import {
|
|
187
|
+
resolveRunnerPath,
|
|
188
|
+
toRunnerDisplayPath
|
|
189
|
+
} from "./chunk-AGSS7277.js";
|
|
168
190
|
import {
|
|
169
191
|
isSpawnableCommand
|
|
170
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-GAQ7OQG6.js";
|
|
171
193
|
import {
|
|
172
194
|
logRunnerAdvisoryOnce,
|
|
173
195
|
resolveRunnerCwd,
|
|
174
196
|
resolveRunnerCwdWithReason
|
|
175
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-DEL2U6CM.js";
|
|
176
198
|
import {
|
|
177
199
|
findLocalBinUpwards,
|
|
178
200
|
localBinPath
|
|
179
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-5VSF4UUQ.js";
|
|
180
202
|
import {
|
|
181
203
|
createAvailabilityProbeFlight,
|
|
182
204
|
getIsolatedNpxSpawnOptions,
|
|
183
205
|
probeToolAsync
|
|
184
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-3KAZU3VR.js";
|
|
185
207
|
import {
|
|
186
208
|
classifyProbeFailure,
|
|
187
209
|
createAvailabilityLatch,
|
|
@@ -191,12 +213,12 @@ import {
|
|
|
191
213
|
logAvailabilityDecision,
|
|
192
214
|
startHostStallSampler,
|
|
193
215
|
transientRetryDelayMs
|
|
194
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-P63GXC37.js";
|
|
195
217
|
import {
|
|
196
218
|
getLspCapableKinds,
|
|
197
219
|
getPrimaryDispatchGroup,
|
|
198
220
|
resolveLanguageRootForFile
|
|
199
|
-
} from "./chunk-
|
|
221
|
+
} from "./chunk-HRNHZA3N.js";
|
|
200
222
|
import {
|
|
201
223
|
getGlobalPiLensDir,
|
|
202
224
|
getProjectDataDir,
|
|
@@ -206,25 +228,25 @@ import {
|
|
|
206
228
|
noteSpawnTimeout,
|
|
207
229
|
resolvePiLensFlag,
|
|
208
230
|
safeSpawnAsync
|
|
209
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-KUA4OJ5Y.js";
|
|
210
232
|
import {
|
|
211
233
|
detectFileKind
|
|
212
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-DUO2TU77.js";
|
|
213
235
|
import {
|
|
214
236
|
classifyGeneratedOrArtifactDetailed,
|
|
215
237
|
detectFileRole,
|
|
216
238
|
loadPiLensProjectConfig,
|
|
217
239
|
resolvePiLensConfig
|
|
218
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-J6MPGQTS.js";
|
|
219
241
|
import {
|
|
220
242
|
findNearestDirWithAnyBasename,
|
|
221
243
|
findNearestDirWithMarker,
|
|
222
244
|
getPiLensGlobalConfigPath
|
|
223
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-5HSRT26B.js";
|
|
224
246
|
import {
|
|
225
247
|
getProjectTrustState,
|
|
226
248
|
projectTrustDenialReason
|
|
227
|
-
} from "./chunk-
|
|
249
|
+
} from "./chunk-M2IFVFWU.js";
|
|
228
250
|
import {
|
|
229
251
|
killedForOutputCap,
|
|
230
252
|
truncatedByOutputCap,
|
|
@@ -233,27 +255,28 @@ import {
|
|
|
233
255
|
import {
|
|
234
256
|
incrementDegradationCount,
|
|
235
257
|
recordDegradationOnce
|
|
236
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-J64T55EI.js";
|
|
237
259
|
import {
|
|
238
260
|
createSubsystemLogger,
|
|
239
261
|
logExtension
|
|
240
|
-
} from "./chunk-
|
|
262
|
+
} from "./chunk-POMLXPMY.js";
|
|
241
263
|
import {
|
|
242
264
|
logLatency,
|
|
243
265
|
phaseFinished,
|
|
244
266
|
phaseStarted
|
|
245
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-QBFBRV2B.js";
|
|
246
268
|
import {
|
|
247
269
|
createNdjsonLogger,
|
|
248
270
|
getGlobalPiLensLogDir,
|
|
249
271
|
getMaxLogSizeMB,
|
|
250
272
|
isTestMode
|
|
251
|
-
} from "./chunk-
|
|
273
|
+
} from "./chunk-YNE3RP52.js";
|
|
252
274
|
import {
|
|
253
275
|
FactStore,
|
|
254
276
|
setFactStoreEvictionReporter
|
|
255
|
-
} from "./chunk-
|
|
277
|
+
} from "./chunk-CYRKQRPM.js";
|
|
256
278
|
import {
|
|
279
|
+
BoundedFifoMap,
|
|
257
280
|
BoundedLruCache
|
|
258
281
|
} from "./chunk-ABBOA7UD.js";
|
|
259
282
|
import {
|
|
@@ -266,7 +289,7 @@ import {
|
|
|
266
289
|
normalizeMapKey,
|
|
267
290
|
pathsEqual,
|
|
268
291
|
toProjectRelativePath
|
|
269
|
-
} from "./chunk-
|
|
292
|
+
} from "./chunk-3RKP3FMS.js";
|
|
270
293
|
|
|
271
294
|
// dist/clients/mcp/analyze.js
|
|
272
295
|
import * as fs19 from "node:fs";
|
|
@@ -885,6 +908,62 @@ function createDiagnosticLogger() {
|
|
|
885
908
|
import * as fs3 from "node:fs";
|
|
886
909
|
import * as path4 from "node:path";
|
|
887
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
|
+
|
|
888
967
|
// dist/clients/dispatch/rule-id-normalize.js
|
|
889
968
|
import * as fs2 from "node:fs";
|
|
890
969
|
import * as path3 from "node:path";
|
|
@@ -1380,8 +1459,8 @@ async function drainPendingRunnerFindings(maxWaitMs = 2e3, currentSession, curre
|
|
|
1380
1459
|
if (maxWaitMs === 0)
|
|
1381
1460
|
await Promise.resolve();
|
|
1382
1461
|
if (maxWaitMs > 0 && current.some((entry) => !entry.settled)) {
|
|
1383
|
-
await new Promise((
|
|
1384
|
-
const timer = setTimeout(
|
|
1462
|
+
await new Promise((resolve45) => {
|
|
1463
|
+
const timer = setTimeout(resolve45, maxWaitMs);
|
|
1385
1464
|
timer.unref?.();
|
|
1386
1465
|
});
|
|
1387
1466
|
}
|
|
@@ -1420,6 +1499,54 @@ function pendingRunnerFindingsSize() {
|
|
|
1420
1499
|
return pending.length;
|
|
1421
1500
|
}
|
|
1422
1501
|
|
|
1502
|
+
// dist/clients/dispatch/adopted-root-runners.js
|
|
1503
|
+
var ADOPTED_ROOT_RUNNER_ALLOWLIST = [
|
|
1504
|
+
"fish-indent",
|
|
1505
|
+
"php-lint"
|
|
1506
|
+
];
|
|
1507
|
+
var ADMITTED = new Set(ADOPTED_ROOT_RUNNER_ALLOWLIST);
|
|
1508
|
+
function isAdoptedRootRunnerAdmitted(runnerId) {
|
|
1509
|
+
return ADMITTED.has(runnerId);
|
|
1510
|
+
}
|
|
1511
|
+
function filterGroupsForAdoptedRoot(groups) {
|
|
1512
|
+
const filtered = [];
|
|
1513
|
+
for (const group of groups) {
|
|
1514
|
+
const runnerIds = [];
|
|
1515
|
+
for (const runnerId of group.runnerIds) {
|
|
1516
|
+
if (isAdoptedRootRunnerAdmitted(runnerId))
|
|
1517
|
+
runnerIds.push(runnerId);
|
|
1518
|
+
}
|
|
1519
|
+
if (runnerIds.length === 0)
|
|
1520
|
+
continue;
|
|
1521
|
+
filtered.push(runnerIds.length === group.runnerIds.length ? group : { ...group, runnerIds });
|
|
1522
|
+
}
|
|
1523
|
+
return filtered;
|
|
1524
|
+
}
|
|
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
|
+
|
|
1423
1550
|
// dist/clients/dispatch/rule-policy.js
|
|
1424
1551
|
function resolvedRulePolicyMap(root) {
|
|
1425
1552
|
const resolved = resolvePiLensConfig({
|
|
@@ -1551,6 +1678,58 @@ function getToolProfile(tool, defectClass) {
|
|
|
1551
1678
|
return TOOL_PROFILE_MAP[t] ?? DEFAULT_TOOL_PROFILE;
|
|
1552
1679
|
}
|
|
1553
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
|
+
|
|
1554
1733
|
// dist/clients/dispatch/utils/format-utils.js
|
|
1555
1734
|
var EMOJI = {
|
|
1556
1735
|
blocking: "\u{1F534}",
|
|
@@ -1805,6 +1984,9 @@ function createDispatchContext(filePath, cwd, pi, facts, blockingOnly, modifiedR
|
|
|
1805
1984
|
}
|
|
1806
1985
|
};
|
|
1807
1986
|
}
|
|
1987
|
+
function deltaBaselineFactKey(filePath) {
|
|
1988
|
+
return `session.baseline.${filePath}`;
|
|
1989
|
+
}
|
|
1808
1990
|
function filterDelta(after, before, keyFn) {
|
|
1809
1991
|
const beforeSet = new Set((before ?? []).map(keyFn));
|
|
1810
1992
|
const afterSet = new Set(after.map(keyFn));
|
|
@@ -1812,17 +1994,6 @@ function filterDelta(after, before, keyFn) {
|
|
|
1812
1994
|
const newItems = after.filter((d) => !beforeSet.has(keyFn(d)));
|
|
1813
1995
|
return { new: newItems, fixed };
|
|
1814
1996
|
}
|
|
1815
|
-
function semanticRank(semantic) {
|
|
1816
|
-
if (semantic === "blocking")
|
|
1817
|
-
return 4;
|
|
1818
|
-
if (semantic === "warning")
|
|
1819
|
-
return 3;
|
|
1820
|
-
if (semantic === "fixed")
|
|
1821
|
-
return 2;
|
|
1822
|
-
if (semantic === "silent")
|
|
1823
|
-
return 1;
|
|
1824
|
-
return 0;
|
|
1825
|
-
}
|
|
1826
1997
|
function toolPriority(tool, defectClass) {
|
|
1827
1998
|
return getToolProfile(tool, defectClass).dedupPriority;
|
|
1828
1999
|
}
|
|
@@ -1921,14 +2092,14 @@ function promoteDeltaUnusedToBlockers(diagnostics) {
|
|
|
1921
2092
|
}
|
|
1922
2093
|
function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
1923
2094
|
if (!ctx.kind)
|
|
1924
|
-
return
|
|
2095
|
+
return {};
|
|
1925
2096
|
const lspEnabled = !ctx.pi.getFlag("no-lsp");
|
|
1926
2097
|
const primary2 = getPrimaryDispatchGroup(ctx.kind, lspEnabled);
|
|
1927
2098
|
if (!primary2 || primary2.runnerIds.length === 0)
|
|
1928
|
-
return
|
|
2099
|
+
return {};
|
|
1929
2100
|
const relevant = runnerLatencies.filter((r) => primary2.runnerIds.includes(r.runnerId));
|
|
1930
2101
|
if (relevant.length === 0)
|
|
1931
|
-
return
|
|
2102
|
+
return {};
|
|
1932
2103
|
const unconfirmedServerIds = [
|
|
1933
2104
|
...new Set(relevant.flatMap((r) => r.unconfirmedServerIds ?? []))
|
|
1934
2105
|
];
|
|
@@ -1945,7 +2116,7 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
1945
2116
|
const onceKey2 = `${ctx.kind}:${ctx.filePath}:${dedupeSet(silentServerIds)}|${dedupeSet(deferredServerIds)}`;
|
|
1946
2117
|
if (dedupe) {
|
|
1947
2118
|
if (coverageNoticeSeen.has(onceKey2))
|
|
1948
|
-
return
|
|
2119
|
+
return {};
|
|
1949
2120
|
coverageNoticeSeen.add(onceKey2);
|
|
1950
2121
|
}
|
|
1951
2122
|
const coverageParts = [];
|
|
@@ -1956,20 +2127,22 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
1956
2127
|
coverageParts.push(`coverage: ${markerFor(silentServerIds)} silent \u2014 diagnostics are incomplete (not a clean result).`);
|
|
1957
2128
|
}
|
|
1958
2129
|
return {
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
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
|
+
}
|
|
1965
2138
|
};
|
|
1966
2139
|
}
|
|
1967
2140
|
const primaryHasCoverage = relevant.some(hasUsableResult);
|
|
1968
2141
|
if (primaryHasCoverage)
|
|
1969
|
-
return
|
|
2142
|
+
return {};
|
|
1970
2143
|
const primaryStillInFlight = relevant.some((r) => r.status === "pending" || r.status === "deferred");
|
|
1971
2144
|
if (primaryStillInFlight)
|
|
1972
|
-
return
|
|
2145
|
+
return {};
|
|
1973
2146
|
const plan = getToolPlan(ctx.kind);
|
|
1974
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)));
|
|
1975
2148
|
const STRUCTURAL_RUNNERS = /* @__PURE__ */ new Set([
|
|
@@ -1982,20 +2155,48 @@ function buildCoverageNotice(ctx, runnerLatencies, dedupe) {
|
|
|
1982
2155
|
const TYPE_CAPABLE_FALLBACK_RUNNERS = /* @__PURE__ */ new Set(["mypy"]);
|
|
1983
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)));
|
|
1984
2157
|
if (anyFallbackHasCoverage)
|
|
1985
|
-
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
|
+
}
|
|
1986
2184
|
const onceKey = `${ctx.kind}:${ctx.filePath}`;
|
|
1987
2185
|
if (dedupe) {
|
|
1988
2186
|
if (coverageNoticeSeen.has(onceKey))
|
|
1989
|
-
return
|
|
2187
|
+
return { unconfirmedStatus };
|
|
1990
2188
|
coverageNoticeSeen.add(onceKey);
|
|
1991
2189
|
}
|
|
1992
2190
|
return {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
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
|
|
1999
2200
|
};
|
|
2000
2201
|
}
|
|
2001
2202
|
var latencyReports = [];
|
|
@@ -2008,10 +2209,29 @@ function clearCoverageNoticeState() {
|
|
|
2008
2209
|
coverageNoticeSeen.clear();
|
|
2009
2210
|
generatedSkipRecorded.clear();
|
|
2010
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
|
+
}
|
|
2011
2224
|
async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
2012
2225
|
const diagnostics = [];
|
|
2013
2226
|
const latencies = [];
|
|
2014
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 = [];
|
|
2015
2235
|
const runnerIds = group.filterKinds ? group.runnerIds.filter((id) => {
|
|
2016
2236
|
const runner = registry.get(id);
|
|
2017
2237
|
return runner && ctx.kind && group.filterKinds?.includes(ctx.kind);
|
|
@@ -2093,6 +2313,7 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2093
2313
|
} catch (error) {
|
|
2094
2314
|
ctx.log(`Runner ${runner.id} precondition failed: ${error}`);
|
|
2095
2315
|
shouldRun = false;
|
|
2316
|
+
inconclusiveRunnerIds.push(runner.id);
|
|
2096
2317
|
}
|
|
2097
2318
|
}
|
|
2098
2319
|
if (!shouldRun) {
|
|
@@ -2117,10 +2338,11 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2117
2338
|
continue;
|
|
2118
2339
|
}
|
|
2119
2340
|
const projectRoot = ctx.projectRoot ?? ctx.cwd;
|
|
2341
|
+
const runnerCtx = runnerDispatchContext(ctx, runner.id);
|
|
2120
2342
|
const observedTier = ctx.writeIndex === void 0 ? "inline" : classifyObservedRunner(projectRoot, runner.id);
|
|
2121
2343
|
if (observedTier === "collect-later") {
|
|
2122
2344
|
const markedAtMs = Date.now();
|
|
2123
|
-
const deferred = runRunner(
|
|
2345
|
+
const deferred = runRunner(runnerCtx, runner, semantic).then((result2) => {
|
|
2124
2346
|
const durationMs = Date.now() - markedAtMs;
|
|
2125
2347
|
const tier2 = observeRunnerLatency({
|
|
2126
2348
|
projectRoot,
|
|
@@ -2187,6 +2409,8 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2187
2409
|
semantic
|
|
2188
2410
|
});
|
|
2189
2411
|
recordRunner(ctx.filePath, runner.id, "pending", 0, 0, ctx.writeIndex);
|
|
2412
|
+
inconclusiveRunnerIds.push(runner.id);
|
|
2413
|
+
collectLaterRunnerIds.push(runner.id);
|
|
2190
2414
|
logLatency({
|
|
2191
2415
|
type: "runner",
|
|
2192
2416
|
filePath: ctx.filePath,
|
|
@@ -2199,7 +2423,7 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2199
2423
|
});
|
|
2200
2424
|
continue;
|
|
2201
2425
|
}
|
|
2202
|
-
const result = await runRunner(
|
|
2426
|
+
const result = await runRunner(runnerCtx, runner, semantic);
|
|
2203
2427
|
onRunnerResult?.(runnerId, result);
|
|
2204
2428
|
const runnerEnd = Date.now();
|
|
2205
2429
|
const duration = runnerEnd - runnerStart;
|
|
@@ -2254,6 +2478,12 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2254
2478
|
},
|
|
2255
2479
|
...result.deferredServerIds !== void 0 && {
|
|
2256
2480
|
deferredServerIds: result.deferredServerIds
|
|
2481
|
+
},
|
|
2482
|
+
...result.primaryUnavailableCause !== void 0 && {
|
|
2483
|
+
primaryUnavailableCause: result.primaryUnavailableCause
|
|
2484
|
+
},
|
|
2485
|
+
...result.disabledPrimaryServerIds !== void 0 && {
|
|
2486
|
+
disabledPrimaryServerIds: result.disabledPrimaryServerIds
|
|
2257
2487
|
}
|
|
2258
2488
|
});
|
|
2259
2489
|
logLatency({
|
|
@@ -2273,7 +2503,28 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2273
2503
|
})) : void 0,
|
|
2274
2504
|
metadata: failureRowMetadata(result) ?? (skipReason ? { skipReason, ...claimSource !== void 0 && { claimSource } } : void 0)
|
|
2275
2505
|
});
|
|
2276
|
-
|
|
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 ?? []);
|
|
2277
2528
|
diagnostics.push(...result.diagnostics);
|
|
2278
2529
|
const resultSemantic = result.semantic ?? semantic;
|
|
2279
2530
|
if (resultSemantic === "blocking" && result.diagnostics.length > 0 || result.diagnostics.some((d) => d.semantic === "blocking")) {
|
|
@@ -2283,22 +2534,50 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
|
|
|
2283
2534
|
break;
|
|
2284
2535
|
}
|
|
2285
2536
|
}
|
|
2286
|
-
return {
|
|
2537
|
+
return {
|
|
2538
|
+
diagnostics,
|
|
2539
|
+
latencies,
|
|
2540
|
+
hadBlocker,
|
|
2541
|
+
outOfEditScope,
|
|
2542
|
+
inconclusiveRunnerIds,
|
|
2543
|
+
inconclusiveServerIds,
|
|
2544
|
+
collectLaterRunnerIds,
|
|
2545
|
+
editScopedRunnerIds,
|
|
2546
|
+
answeredRunnerIds,
|
|
2547
|
+
coveredRunners
|
|
2548
|
+
};
|
|
2287
2549
|
}
|
|
2288
2550
|
async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
2289
2551
|
const _overallStart = Date.now();
|
|
2290
2552
|
if (ctx.analysisRootMode === "adopted") {
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2553
|
+
const planned = groups.flatMap((g) => g.runnerIds);
|
|
2554
|
+
groups = filterGroupsForAdoptedRoot(groups);
|
|
2555
|
+
const admitted = new Set(groups.flatMap((g) => g.runnerIds));
|
|
2556
|
+
logLatency({
|
|
2557
|
+
type: "phase",
|
|
2558
|
+
filePath: ctx.filePath,
|
|
2559
|
+
phase: "dispatch_adopted_root_allowlist",
|
|
2560
|
+
durationMs: 0,
|
|
2561
|
+
metadata: {
|
|
2562
|
+
admissionList: ADOPTED_ROOT_RUNNER_ALLOWLIST.join(","),
|
|
2563
|
+
admitted: groups.flatMap((g) => g.runnerIds).join(","),
|
|
2564
|
+
refused: planned.flatMap((id) => admitted.has(id) ? [] : [id]).join(","),
|
|
2565
|
+
noAdmittedRunner: groups.length === 0
|
|
2566
|
+
}
|
|
2567
|
+
});
|
|
2568
|
+
if (groups.length === 0) {
|
|
2569
|
+
return {
|
|
2570
|
+
diagnostics: [],
|
|
2571
|
+
blockers: [],
|
|
2572
|
+
warnings: [],
|
|
2573
|
+
baselineWarningCount: 0,
|
|
2574
|
+
fixed: [],
|
|
2575
|
+
resolvedCount: 0,
|
|
2576
|
+
output: "",
|
|
2577
|
+
blockerOutput: "",
|
|
2578
|
+
hasBlockers: false
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2302
2581
|
}
|
|
2303
2582
|
if (ctx.fileRole === "generated") {
|
|
2304
2583
|
const evidence = ctx.generatedEvidence;
|
|
@@ -2340,7 +2619,8 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2340
2619
|
metadata: {
|
|
2341
2620
|
groupCount: groups.length,
|
|
2342
2621
|
kind: ctx.kind,
|
|
2343
|
-
runners: allRunnerIds.join(",")
|
|
2622
|
+
runners: allRunnerIds.join(","),
|
|
2623
|
+
...ctx.preEditCapture && { preEditCapture: true }
|
|
2344
2624
|
}
|
|
2345
2625
|
});
|
|
2346
2626
|
const groupResults = await Promise.all(groups.map((group) => runGroup(ctx, group, registry, onRunnerResult)));
|
|
@@ -2352,17 +2632,51 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2352
2632
|
reason: "dispatchForFile requires an absolute ctx.filePath to key the delta baseline (refs #2489)"
|
|
2353
2633
|
});
|
|
2354
2634
|
}
|
|
2355
|
-
const baselineAbsKey =
|
|
2635
|
+
const baselineAbsKey = deltaBaselineFactKey(ctx.filePath);
|
|
2356
2636
|
const previousBaseline = ctx.deltaMode && baselinePathSafe ? ctx.facts.getBoundedSessionFact(baselineAbsKey) : void 0;
|
|
2357
2637
|
const baselineWarnings = previousBaseline?.filter((d) => d.semantic === "warning" || d.semantic === "none");
|
|
2358
2638
|
const baselineWarningCount = baselineWarnings?.length ?? 0;
|
|
2359
|
-
|
|
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) {
|
|
2360
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);
|
|
2361
2659
|
allDiagnostics.push(...groupDiags);
|
|
2362
2660
|
if (hadBlocker)
|
|
2363
2661
|
stopped = true;
|
|
2364
2662
|
}
|
|
2365
|
-
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);
|
|
2366
2680
|
const fileContent = ctx.facts.getFileFact(ctx.filePath, "file.content") ?? "";
|
|
2367
2681
|
const rulePolicy = ctx.rulePolicy ?? rulePolicyMapFromConfig(loadPiLensProjectConfig(ctx.projectRoot ?? ctx.cwd).rules);
|
|
2368
2682
|
const applyOutputFilters = (diags) => {
|
|
@@ -2377,11 +2691,33 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2377
2691
|
};
|
|
2378
2692
|
let visibleDiagnostics = applyOutputFilters(dedupedDiagnostics);
|
|
2379
2693
|
let resolvedCount = 0;
|
|
2694
|
+
const stillObserved = outOfEditScope.length > 0 ? applyOutputFilters(outOfEditScope).flatMap((d) => d.semantic === "blocking" ? [d] : []) : [];
|
|
2695
|
+
let heldBackBlockers = [];
|
|
2380
2696
|
if (ctx.deltaMode && previousBaseline) {
|
|
2381
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] : [])));
|
|
2382
2701
|
visibleDiagnostics = promoteDeltaUnusedToBlockers(filtered.new);
|
|
2383
2702
|
resolvedCount = filtered.fixed.length;
|
|
2384
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
|
+
}
|
|
2385
2721
|
if (ctx.deltaMode && baselinePathSafe) {
|
|
2386
2722
|
ctx.facts.setBoundedSessionFact(baselineAbsKey, [...dedupedDiagnostics]);
|
|
2387
2723
|
}
|
|
@@ -2393,21 +2729,21 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2393
2729
|
provider: ctx.telemetryProvider
|
|
2394
2730
|
};
|
|
2395
2731
|
if (fixedItems.length > 0) {
|
|
2396
|
-
import("./chunk-
|
|
2732
|
+
import("./chunk-JUKMK5Y4.js").then(({ appendToWorklog }) => {
|
|
2397
2733
|
appendToWorklog(ctx.cwd, fixedItems, true, worklogIdentity);
|
|
2398
2734
|
}).catch(() => {
|
|
2399
2735
|
});
|
|
2400
2736
|
}
|
|
2401
2737
|
const fixableWarnings = warnings.filter((d) => d.fixable);
|
|
2402
2738
|
if (fixableWarnings.length > 0) {
|
|
2403
|
-
import("./chunk-
|
|
2739
|
+
import("./chunk-JUKMK5Y4.js").then(({ appendToWorklog }) => {
|
|
2404
2740
|
appendToWorklog(ctx.cwd, fixableWarnings, false, worklogIdentity);
|
|
2405
2741
|
}).catch(() => {
|
|
2406
2742
|
});
|
|
2407
2743
|
}
|
|
2408
2744
|
const inlineBlockers = blockers;
|
|
2409
2745
|
const inlineFixed = fixedItems;
|
|
2410
|
-
const coverageNotice = buildCoverageNotice(ctx, runnerLatencies, options?.dedupeCoverageNotice ?? true);
|
|
2746
|
+
const { notice: coverageNotice, unconfirmedStatus } = buildCoverageNotice(ctx, runnerLatencies, options?.dedupeCoverageNotice ?? true);
|
|
2411
2747
|
const blockerOutput = formatDiagnostics(inlineBlockers, "blocking");
|
|
2412
2748
|
let output = blockerOutput;
|
|
2413
2749
|
output += formatDiagnostics(inlineFixed, "fixed");
|
|
@@ -2463,7 +2799,19 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2463
2799
|
// (above, `metadata: { groupCount, kind, runners }`) fires before the
|
|
2464
2800
|
// baseline read ever runs and cannot carry either value.
|
|
2465
2801
|
baselineHit: previousBaseline !== void 0,
|
|
2466
|
-
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
|
|
2467
2815
|
}
|
|
2468
2816
|
});
|
|
2469
2817
|
return {
|
|
@@ -2476,7 +2824,21 @@ async function dispatchForFile(ctx, groups, registry, onRunnerResult, options) {
|
|
|
2476
2824
|
resolvedCount,
|
|
2477
2825
|
output,
|
|
2478
2826
|
blockerOutput,
|
|
2479
|
-
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 }
|
|
2480
2842
|
};
|
|
2481
2843
|
}
|
|
2482
2844
|
var RUNNER_TIMEOUT_MS = RUNTIME_CONFIG.dispatch.runnerTimeoutMs;
|
|
@@ -2557,6 +2919,16 @@ var DEFAULT_NEIGHBOUR_BUDGET = 40;
|
|
|
2557
2919
|
var CASCADE_NEIGHBOUR_BUDGET = Math.max(MIN_NEIGHBOUR_BUDGET, Number.parseInt(process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET ?? "40", 10) || DEFAULT_NEIGHBOUR_BUDGET);
|
|
2558
2920
|
var NEIGHBOUR_BUDGET_OVERRIDDEN = process.env.PI_LENS_CASCADE_NEIGHBOUR_BUDGET !== void 0 && CASCADE_NEIGHBOUR_BUDGET !== DEFAULT_NEIGHBOUR_BUDGET;
|
|
2559
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
|
+
|
|
2560
2932
|
// dist/clients/dispatch/utils/lsp-diagnostics.js
|
|
2561
2933
|
function convertLspDiagnostics(diags, filePath, options = {}) {
|
|
2562
2934
|
const tool = options.tool ?? "lsp";
|
|
@@ -2585,7 +2957,10 @@ function convertLspDiagnostics(diags, filePath, options = {}) {
|
|
|
2585
2957
|
autoFixAvailable: false,
|
|
2586
2958
|
fixKind: hasSuggestion ? "suggestion" : void 0,
|
|
2587
2959
|
fixSuggestion: options.fixSuggestionByIndex?.get(idx),
|
|
2588
|
-
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 }
|
|
2589
2964
|
};
|
|
2590
2965
|
});
|
|
2591
2966
|
}
|
|
@@ -2599,7 +2974,8 @@ function applyFindingPolicy(diagnostics, options) {
|
|
|
2599
2974
|
root: options.cwd,
|
|
2600
2975
|
filePath: options.filePath
|
|
2601
2976
|
}),
|
|
2602
|
-
inlineKept
|
|
2977
|
+
inlineKept,
|
|
2978
|
+
disposed
|
|
2603
2979
|
};
|
|
2604
2980
|
}
|
|
2605
2981
|
function loadProjectRulePolicyMap(cwd) {
|
|
@@ -2664,6 +3040,28 @@ function applyPushedFindingPolicy(findings, options) {
|
|
|
2664
3040
|
});
|
|
2665
3041
|
return { kept, suppressed: findings.length - kept.length };
|
|
2666
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
|
+
}
|
|
2667
3065
|
function expandRenderedIdentities(rendered) {
|
|
2668
3066
|
const out = [];
|
|
2669
3067
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2774,6 +3172,12 @@ function formatCacheAgeLabel(scannedAt, nowMs = Date.now()) {
|
|
|
2774
3172
|
const remMinutes = ageMinutes % 60;
|
|
2775
3173
|
return remMinutes === 0 ? `scanned ${ageHours}h ago` : `scanned ${ageHours}h ${remMinutes}m ago`;
|
|
2776
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
|
+
}
|
|
2777
3181
|
function admitsProjectWideFindings(sessionRole) {
|
|
2778
3182
|
return sessionRole === "primary";
|
|
2779
3183
|
}
|
|
@@ -2887,6 +3291,17 @@ var DELIVERY_SURFACES = {
|
|
|
2887
3291
|
{ evidenceMin: 2 }
|
|
2888
3292
|
),
|
|
2889
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"]),
|
|
2890
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 }),
|
|
2891
3306
|
// #3102: the cold-neighbour cascade run is BUILT here, in the quiet-window
|
|
2892
3307
|
// reconcile (`onResolvedFound` in index.ts), a turn earlier than the
|
|
@@ -2975,16 +3390,185 @@ var DELIVERY_SURFACES = {
|
|
|
2975
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"),
|
|
2976
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"),
|
|
2977
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"),
|
|
2978
|
-
"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")
|
|
2979
3421
|
};
|
|
2980
3422
|
|
|
2981
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
|
+
}
|
|
2982
3491
|
function cascadeCarrySuffix(carriedTurns, observedAt) {
|
|
2983
3492
|
if (carriedTurns === void 0 || carriedTurns < 1)
|
|
2984
3493
|
return void 0;
|
|
2985
3494
|
const noun = carriedTurns === 1 ? "turn" : "turns";
|
|
2986
3495
|
return `(carried ${carriedTurns} ${noun} \xB7 ${formatCacheAgeLabel(observedAt)})`;
|
|
2987
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
|
+
}
|
|
2988
3572
|
|
|
2989
3573
|
// dist/clients/cascade-logger.js
|
|
2990
3574
|
import * as path5 from "node:path";
|
|
@@ -3097,33 +3681,152 @@ function createDiagnosticTracker() {
|
|
|
3097
3681
|
}
|
|
3098
3682
|
|
|
3099
3683
|
// dist/clients/lsp/cascade-tier.js
|
|
3684
|
+
var MAX_OUTSTANDING_TOUCHES = 256;
|
|
3100
3685
|
var OUTSTANDING_TOUCH_MAX_AGE_MS = 15 * 6e4;
|
|
3101
|
-
var _outstandingTouches =
|
|
3686
|
+
var _outstandingTouches = new BoundedFifoMap(MAX_OUTSTANDING_TOUCHES);
|
|
3102
3687
|
var _expiredSinceLastSweep = 0;
|
|
3103
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
|
+
}
|
|
3104
3780
|
function resetCascadeTierSessionState() {
|
|
3781
|
+
const dropped = _outstandingTouches.size;
|
|
3105
3782
|
_outstandingTouches.clear();
|
|
3106
3783
|
_expiredSinceLastSweep = 0;
|
|
3107
3784
|
_evictedSinceLastSweep = 0;
|
|
3785
|
+
if (dropped > 0) {
|
|
3786
|
+
logCascade({
|
|
3787
|
+
phase: "cascade_tier3_dropped",
|
|
3788
|
+
filePath: "<session-reset>",
|
|
3789
|
+
metadata: { count: dropped }
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3108
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 = {};
|
|
3109
3825
|
|
|
3110
3826
|
// dist/clients/dispatch/runners/ast-grep-napi.js
|
|
3111
|
-
import * as
|
|
3827
|
+
import * as fs5 from "node:fs";
|
|
3112
3828
|
import * as path6 from "node:path";
|
|
3113
3829
|
|
|
3114
|
-
// dist/clients/deps/ast-grep-napi.js
|
|
3115
|
-
import { createRequire } from "node:module";
|
|
3116
|
-
import { pathToFileURL } from "node:url";
|
|
3117
|
-
var _require = createRequire(import.meta.url);
|
|
3118
|
-
function loadAstGrepNapi() {
|
|
3119
|
-
try {
|
|
3120
|
-
const entry = _require.resolve("@ast-grep/napi");
|
|
3121
|
-
return import(pathToFileURL(entry).href);
|
|
3122
|
-
} catch {
|
|
3123
|
-
return import("@ast-grep/napi");
|
|
3124
|
-
}
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
3830
|
// dist/clients/dispatch/priorities.js
|
|
3128
3831
|
var PRIORITY = {
|
|
3129
3832
|
LSP_PRIMARY: 4,
|
|
@@ -3140,6 +3843,66 @@ var PRIORITY = {
|
|
|
3140
3843
|
DEEP_LANGUAGE_ANALYSIS: 50
|
|
3141
3844
|
};
|
|
3142
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
|
+
|
|
3143
3906
|
// dist/clients/dispatch/runners/ast-grep-napi.js
|
|
3144
3907
|
var defaultUnsupportedLanguageLog = /* @__PURE__ */ new Set();
|
|
3145
3908
|
var UNSUPPORTED_RULE_ID_SAMPLE_SIZE = 5;
|
|
@@ -3657,12 +4420,19 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3657
4420
|
}
|
|
3658
4421
|
if (!rule.rule)
|
|
3659
4422
|
continue;
|
|
4423
|
+
if (options.content !== void 0 && !ruleCanMatchText(rule, options.content)) {
|
|
4424
|
+
continue;
|
|
4425
|
+
}
|
|
3660
4426
|
try {
|
|
3661
4427
|
const scopes = runsInsideHtmlScript ? htmlInjections.map((injection) => ({
|
|
3662
4428
|
root: injection.root,
|
|
3663
4429
|
position(match) {
|
|
3664
4430
|
const start = match.range().start;
|
|
3665
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;
|
|
3666
4436
|
}
|
|
3667
4437
|
})) : [
|
|
3668
4438
|
{
|
|
@@ -3670,6 +4440,9 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3670
4440
|
position(match) {
|
|
3671
4441
|
const start = match.range().start;
|
|
3672
4442
|
return { line: start.line, column: start.column };
|
|
4443
|
+
},
|
|
4444
|
+
endLine(match) {
|
|
4445
|
+
return match.range().end.line;
|
|
3673
4446
|
}
|
|
3674
4447
|
}
|
|
3675
4448
|
];
|
|
@@ -3679,7 +4452,9 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3679
4452
|
if (rule.utils)
|
|
3680
4453
|
nativeConfig.utils = rule.utils;
|
|
3681
4454
|
const collected = [];
|
|
4455
|
+
const withheld = [];
|
|
3682
4456
|
let rejectLogged = false;
|
|
4457
|
+
const editScoped = options.modifiedRanges !== void 0 && normalizeRuleSeverity(rule.severity) === "error";
|
|
3683
4458
|
for (const scope of scopes) {
|
|
3684
4459
|
let found;
|
|
3685
4460
|
try {
|
|
@@ -3694,19 +4469,23 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3694
4469
|
for (const match of found) {
|
|
3695
4470
|
if (collected.length >= maxMatchesPerRule)
|
|
3696
4471
|
break;
|
|
3697
|
-
|
|
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 });
|
|
3698
4479
|
}
|
|
3699
4480
|
if (collected.length >= maxMatchesPerRule)
|
|
3700
4481
|
break;
|
|
3701
4482
|
}
|
|
3702
|
-
|
|
3703
|
-
if (diagnostics.length >= maxTotalDiagnostics)
|
|
3704
|
-
break;
|
|
4483
|
+
const toDiagnostic3 = (position) => {
|
|
3705
4484
|
const severity = normalizeRuleSeverity(rule.severity);
|
|
3706
4485
|
const semantic = severity === "error" ? "blocking" : "warning";
|
|
3707
4486
|
const defectClass = classifyDefect(rule.id, "ast-grep-napi", rule.message || rule.id);
|
|
3708
4487
|
const ruleFix = explicitRuleFixSuggestion(rule);
|
|
3709
|
-
|
|
4488
|
+
return {
|
|
3710
4489
|
id: `ast-grep-napi-${position.line}-${rule.id}`,
|
|
3711
4490
|
message: `[${rule.metadata?.category || "slop"}] ${rule.message || rule.id}`,
|
|
3712
4491
|
filePath,
|
|
@@ -3721,7 +4500,15 @@ function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}) {
|
|
|
3721
4500
|
autoFixAvailable: false,
|
|
3722
4501
|
fixKind: ruleFix ? "suggestion" : void 0,
|
|
3723
4502
|
fixSuggestion: semantic === "blocking" ? ruleFix ?? defaultFixSuggestion(defectClass, rule.id) : ruleFix
|
|
3724
|
-
}
|
|
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));
|
|
3725
4512
|
}
|
|
3726
4513
|
if (diagnostics.length >= maxTotalDiagnostics)
|
|
3727
4514
|
break;
|
|
@@ -3743,8 +4530,10 @@ var astGrepNapiRunner = {
|
|
|
3743
4530
|
}
|
|
3744
4531
|
const astGrepLspEnabled = enabledAuxiliaryLspServerIds((f) => ctx.pi?.getFlag?.(f)).includes("ast-grep");
|
|
3745
4532
|
const astGrepLspPublished = astGrepLspEnabled ? await hasAuxiliaryLspPublishedForRoot("ast-grep", ctx.filePath) : false;
|
|
3746
|
-
|
|
3747
|
-
|
|
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) {
|
|
3748
4537
|
incrementDegradationCount({
|
|
3749
4538
|
kind: "aux-runner-findings-lost",
|
|
3750
4539
|
subject: "ast-grep",
|
|
@@ -3753,13 +4542,23 @@ var astGrepNapiRunner = {
|
|
|
3753
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})`
|
|
3754
4543
|
});
|
|
3755
4544
|
}
|
|
3756
|
-
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
|
+
};
|
|
3757
4556
|
}
|
|
3758
4557
|
const sgModule = await loadSg();
|
|
3759
4558
|
if (!sgModule) {
|
|
3760
4559
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3761
4560
|
}
|
|
3762
|
-
if (!
|
|
4561
|
+
if (!fs5.existsSync(ctx.filePath)) {
|
|
3763
4562
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3764
4563
|
}
|
|
3765
4564
|
const lang = getLang(ctx.filePath, sgModule);
|
|
@@ -3768,7 +4567,7 @@ var astGrepNapiRunner = {
|
|
|
3768
4567
|
}
|
|
3769
4568
|
let stats;
|
|
3770
4569
|
try {
|
|
3771
|
-
stats =
|
|
4570
|
+
stats = fs5.statSync(ctx.filePath);
|
|
3772
4571
|
} catch {
|
|
3773
4572
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3774
4573
|
}
|
|
@@ -3781,7 +4580,7 @@ var astGrepNapiRunner = {
|
|
|
3781
4580
|
content = contentFromFacts;
|
|
3782
4581
|
} else {
|
|
3783
4582
|
try {
|
|
3784
|
-
content =
|
|
4583
|
+
content = fs5.readFileSync(ctx.filePath, "utf-8");
|
|
3785
4584
|
} catch {
|
|
3786
4585
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
3787
4586
|
}
|
|
@@ -3803,10 +4602,16 @@ var astGrepNapiRunner = {
|
|
|
3803
4602
|
recordNapiFallbackCoverage(ctx.filePath);
|
|
3804
4603
|
clearPendingAuxiliaryCoverage(ctx.filePath, "ast-grep");
|
|
3805
4604
|
}
|
|
4605
|
+
const outOfEditScope = [];
|
|
3806
4606
|
const diagnostics = evaluateAstGrepRules(ctx.filePath, rootNode, ctx.cwd, ctx.kind, {
|
|
3807
4607
|
blockingOnly: runningAsLspSubstitute ? false : ctx.blockingOnly,
|
|
3808
4608
|
projectRoot: ctx.projectRoot,
|
|
3809
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,
|
|
3810
4615
|
log: (message) => ctx.log(message),
|
|
3811
4616
|
content,
|
|
3812
4617
|
sgModule
|
|
@@ -3836,10 +4641,16 @@ var astGrepNapiRunner = {
|
|
|
3836
4641
|
} else if (diagnostics.length > 0) {
|
|
3837
4642
|
semantic = "warning";
|
|
3838
4643
|
}
|
|
3839
|
-
return
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
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
|
+
};
|
|
3843
4654
|
}
|
|
3844
4655
|
};
|
|
3845
4656
|
var ast_grep_napi_default = astGrepNapiRunner;
|
|
@@ -4380,7 +5191,7 @@ var biomeCheckJsonRunner = {
|
|
|
4380
5191
|
var biome_check_default = biomeCheckJsonRunner;
|
|
4381
5192
|
|
|
4382
5193
|
// dist/clients/dispatch/runners/cpp-check.js
|
|
4383
|
-
import * as
|
|
5194
|
+
import * as fs6 from "node:fs";
|
|
4384
5195
|
import * as path9 from "node:path";
|
|
4385
5196
|
var compilerCheckers = {
|
|
4386
5197
|
clang: createAvailabilityChecker("clang", ".exe"),
|
|
@@ -4419,7 +5230,7 @@ var CPP_HEADER_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4419
5230
|
]);
|
|
4420
5231
|
function headerLooksLikeCpp(absPath) {
|
|
4421
5232
|
try {
|
|
4422
|
-
const content =
|
|
5233
|
+
const content = fs6.readFileSync(absPath, "utf-8");
|
|
4423
5234
|
return /\b(namespace|template|class|constexpr|concept|using)\b|std::|\b(public|private|protected)\s*:/.test(content);
|
|
4424
5235
|
} catch {
|
|
4425
5236
|
return false;
|
|
@@ -4570,7 +5381,7 @@ var cpp_check_default = cppCheckRunner;
|
|
|
4570
5381
|
|
|
4571
5382
|
// dist/clients/dispatch/runners/credo.js
|
|
4572
5383
|
import * as path10 from "node:path";
|
|
4573
|
-
import * as
|
|
5384
|
+
import * as fs7 from "node:fs";
|
|
4574
5385
|
var CREDO_PROBE_BUDGET_MS = 1e4;
|
|
4575
5386
|
var probeCredo = createCwdCachedProbe((cwd) => safeSpawnAsync("mix", ["credo", "--version"], {
|
|
4576
5387
|
timeout: CREDO_PROBE_BUDGET_MS,
|
|
@@ -4596,7 +5407,7 @@ function parseCredoJson(raw, fallbackPath, cwd) {
|
|
|
4596
5407
|
}
|
|
4597
5408
|
}
|
|
4598
5409
|
function hasMixExs(cwd) {
|
|
4599
|
-
return
|
|
5410
|
+
return fs7.existsSync(path10.join(cwd, "mix.exs"));
|
|
4600
5411
|
}
|
|
4601
5412
|
var credoRunner = {
|
|
4602
5413
|
id: "credo",
|
|
@@ -4633,7 +5444,7 @@ var credoRunner = {
|
|
|
4633
5444
|
var credo_default = credoRunner;
|
|
4634
5445
|
|
|
4635
5446
|
// dist/clients/dispatch/runners/cue-vet.js
|
|
4636
|
-
import * as
|
|
5447
|
+
import * as fs8 from "node:fs";
|
|
4637
5448
|
import * as path11 from "node:path";
|
|
4638
5449
|
var cue = createAvailabilityChecker("cue", ".exe", ["version"]);
|
|
4639
5450
|
function parseCueVetOutput(raw) {
|
|
@@ -4738,7 +5549,7 @@ var cueVetRunner = {
|
|
|
4738
5549
|
const singleFileArgs = ["vet", "-c=false", `./${fileName}`];
|
|
4739
5550
|
let touchedContent = null;
|
|
4740
5551
|
try {
|
|
4741
|
-
touchedContent =
|
|
5552
|
+
touchedContent = fs8.readFileSync(absPath, "utf8");
|
|
4742
5553
|
} catch {
|
|
4743
5554
|
touchedContent = null;
|
|
4744
5555
|
}
|
|
@@ -4943,8 +5754,11 @@ var dartAnalyzeRunner = {
|
|
|
4943
5754
|
const parsed = parseToolRun("dart-analyze", {
|
|
4944
5755
|
result,
|
|
4945
5756
|
output: raw,
|
|
4946
|
-
// EXIT TABLE (Dart 3.
|
|
4947
|
-
|
|
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] }
|
|
4948
5762
|
}, (out) => parseDartMachineOutput(out, ctx.filePath, cwd));
|
|
4949
5763
|
if (parsed.skipped)
|
|
4950
5764
|
return parsed.skipped;
|
|
@@ -4959,7 +5773,7 @@ var dartAnalyzeRunner = {
|
|
|
4959
5773
|
var dart_analyze_default = dartAnalyzeRunner;
|
|
4960
5774
|
|
|
4961
5775
|
// dist/clients/dispatch/runners/detekt.js
|
|
4962
|
-
import * as
|
|
5776
|
+
import * as fs9 from "node:fs";
|
|
4963
5777
|
import * as path13 from "node:path";
|
|
4964
5778
|
var detekt = createAvailabilityChecker("detekt", ".bat");
|
|
4965
5779
|
var DETEKT_CONFIG_CANDIDATES = [
|
|
@@ -5033,7 +5847,7 @@ var DETEKT_FIXABLE_RULES = /* @__PURE__ */ new Set([
|
|
|
5033
5847
|
function findDetektConfig(cwd) {
|
|
5034
5848
|
for (const candidate of DETEKT_CONFIG_CANDIDATES) {
|
|
5035
5849
|
const full = path13.join(cwd, candidate);
|
|
5036
|
-
if (
|
|
5850
|
+
if (fs9.existsSync(full))
|
|
5037
5851
|
return full;
|
|
5038
5852
|
}
|
|
5039
5853
|
return void 0;
|
|
@@ -5112,11 +5926,11 @@ var detektRunner = {
|
|
|
5112
5926
|
var detekt_default = detektRunner;
|
|
5113
5927
|
|
|
5114
5928
|
// dist/clients/dispatch/runners/dotnet-build.js
|
|
5115
|
-
import * as
|
|
5929
|
+
import * as fs10 from "node:fs";
|
|
5116
5930
|
import * as path14 from "node:path";
|
|
5117
5931
|
var dotnet = createAvailabilityChecker("dotnet", ".exe");
|
|
5118
5932
|
function findProjectTarget(cwd) {
|
|
5119
|
-
const entries =
|
|
5933
|
+
const entries = fs10.readdirSync(cwd);
|
|
5120
5934
|
const solution = entries.find((entry) => /\.(sln|slnx)$/i.test(entry));
|
|
5121
5935
|
if (solution)
|
|
5122
5936
|
return solution;
|
|
@@ -5266,12 +6080,12 @@ ${result.stderr ?? ""}`.trim();
|
|
|
5266
6080
|
var dotnet_build_default = dotnetBuildRunner;
|
|
5267
6081
|
|
|
5268
6082
|
// dist/clients/dispatch/runners/elixir-check.js
|
|
5269
|
-
import * as
|
|
6083
|
+
import * as fs11 from "node:fs";
|
|
5270
6084
|
import * as path15 from "node:path";
|
|
5271
6085
|
var mix = createAvailabilityChecker("mix", ".bat");
|
|
5272
6086
|
var elixirc = createAvailabilityChecker("elixirc", ".bat");
|
|
5273
6087
|
function hasMixExs2(cwd) {
|
|
5274
|
-
return
|
|
6088
|
+
return fs11.existsSync(path15.join(cwd, "mix.exs"));
|
|
5275
6089
|
}
|
|
5276
6090
|
var ELIXIR_SNIPPET_LOCATION = /└─\s+(.+?):(\d+)(?::(\d+))?(?::|$)/;
|
|
5277
6091
|
function parseElixirOutput(raw, filePath, cwd = process.cwd()) {
|
|
@@ -5371,7 +6185,7 @@ var elixirCheckRunner = {
|
|
|
5371
6185
|
args = ["compile", "--warnings-as-errors"];
|
|
5372
6186
|
} else if (await elixirc.isAvailableAsync(cwd)) {
|
|
5373
6187
|
const outDir = path15.join(getProjectDataDir(cwd), "elixir-check");
|
|
5374
|
-
|
|
6188
|
+
fs11.mkdirSync(outDir, { recursive: true });
|
|
5375
6189
|
command = "elixirc";
|
|
5376
6190
|
args = ["-o", outDir, absPath];
|
|
5377
6191
|
}
|
|
@@ -5706,9 +6520,10 @@ var parseRuffOutput = createLineParser({
|
|
|
5706
6520
|
autoFixAvailable: ruffAutofix?.safePipelineAutofix ?? false,
|
|
5707
6521
|
fixKind: ruffAutofix?.fixKind === "none" ? void 0 : ruffAutofix?.fixKind
|
|
5708
6522
|
});
|
|
6523
|
+
var GO_VET_LINE = /^(?:vet:\s+)?(.+?):(\d+):(\d+):\s*(.+)/;
|
|
5709
6524
|
var parseGoVetOutput = createLineParser({
|
|
5710
6525
|
tool: "go-vet",
|
|
5711
|
-
regex:
|
|
6526
|
+
regex: GO_VET_LINE,
|
|
5712
6527
|
extractMessage: (m) => m[4],
|
|
5713
6528
|
generateId: (m) => `go-vet-${m[2]}`,
|
|
5714
6529
|
defectClass: "correctness"
|
|
@@ -5750,7 +6565,7 @@ var goVetRunner = {
|
|
|
5750
6565
|
}
|
|
5751
6566
|
const absTarget = resolve14(ctx.filePath);
|
|
5752
6567
|
const relevant = raw.split("\n").filter((line) => {
|
|
5753
|
-
const m = line.match(
|
|
6568
|
+
const m = line.match(GO_VET_LINE);
|
|
5754
6569
|
return m != null && pathsEqual(resolve14(cwd, m[1].trim()), absTarget);
|
|
5755
6570
|
}).join("\n");
|
|
5756
6571
|
const diagnostics = parseGoVetOutput(relevant, ctx.filePath, cwd);
|
|
@@ -5762,6 +6577,16 @@ var go_vet_default = goVetRunner;
|
|
|
5762
6577
|
// dist/clients/dispatch/runners/golangci-lint.js
|
|
5763
6578
|
import * as path19 from "node:path";
|
|
5764
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
|
+
];
|
|
5765
6590
|
function describeReplacement(replacement) {
|
|
5766
6591
|
if (!replacement)
|
|
5767
6592
|
return void 0;
|
|
@@ -5822,12 +6647,18 @@ var golangciRunner = {
|
|
|
5822
6647
|
const cmd = await resolveAvailableOrInstall(golangci, "golangci-lint", cwd);
|
|
5823
6648
|
if (!cmd)
|
|
5824
6649
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
5825
|
-
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 });
|
|
5826
6657
|
const raw = (result.stdout ?? "").length > 0 ? result.stdout ?? "" : result.status !== 0 ? result.stderr || "" : "";
|
|
5827
6658
|
const parsed = parseToolRun("golangci-lint", {
|
|
5828
6659
|
result,
|
|
5829
6660
|
output: raw,
|
|
5830
|
-
// 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.
|
|
5831
6662
|
exitCodes: { ran: [1, 2, 3, 4, 5] }
|
|
5832
6663
|
}, (raw2) => parseGolangciJson(raw2, ctx.filePath, cwd));
|
|
5833
6664
|
if (parsed.skipped)
|
|
@@ -5922,7 +6753,7 @@ var hadolint_default = hadolintRunner;
|
|
|
5922
6753
|
|
|
5923
6754
|
// dist/clients/dispatch/runners/helm-lint.js
|
|
5924
6755
|
import * as path21 from "node:path";
|
|
5925
|
-
var helm = createAvailabilityChecker("helm", ".exe");
|
|
6756
|
+
var helm = createAvailabilityChecker("helm", ".exe", ["version", "--short"]);
|
|
5926
6757
|
var inFlightByChartRoot = new PathKeyedMap(normalizeMapKey);
|
|
5927
6758
|
var HELM_LINT_TIMEOUT_MS = 3e4;
|
|
5928
6759
|
var MAX_HELM_LINT_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
@@ -5936,14 +6767,17 @@ function isWithin(root, candidate) {
|
|
|
5936
6767
|
return relative5 === "" || !relative5.startsWith(`..${path21.sep}`) && relative5 !== ".." && !path21.isAbsolute(relative5);
|
|
5937
6768
|
}
|
|
5938
6769
|
function diagnosticLocation(message, chartRoot) {
|
|
5939
|
-
const location = message.match(/(
|
|
5940
|
-
|
|
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) {
|
|
5941
6773
|
return { filePath: path21.join(chartRoot, "Chart.yaml"), message };
|
|
5942
6774
|
}
|
|
5943
|
-
const
|
|
6775
|
+
const embedded = !message.startsWith(found);
|
|
6776
|
+
const relative5 = embedded ? found.slice(found.indexOf("/") + 1) : found;
|
|
6777
|
+
const candidate = path21.resolve(chartRoot, relative5);
|
|
5944
6778
|
return {
|
|
5945
6779
|
filePath: isWithin(chartRoot, candidate) ? candidate : path21.join(chartRoot, "Chart.yaml"),
|
|
5946
|
-
line:
|
|
6780
|
+
line: rawLine ? Number(rawLine) : void 0,
|
|
5947
6781
|
message
|
|
5948
6782
|
};
|
|
5949
6783
|
}
|
|
@@ -6058,10 +6892,10 @@ var helmLintRunner = {
|
|
|
6058
6892
|
var helm_lint_default = helmLintRunner;
|
|
6059
6893
|
|
|
6060
6894
|
// dist/clients/dispatch/runners/helm-render.js
|
|
6061
|
-
import * as
|
|
6895
|
+
import * as fs12 from "node:fs";
|
|
6062
6896
|
import * as os from "node:os";
|
|
6063
6897
|
import * as path22 from "node:path";
|
|
6064
|
-
var helm2 = createAvailabilityChecker("helm", ".exe");
|
|
6898
|
+
var helm2 = createAvailabilityChecker("helm", ".exe", ["version", "--short"]);
|
|
6065
6899
|
var trivy = createAvailabilityChecker("trivy", ".exe");
|
|
6066
6900
|
var inFlightByChartRoot2 = new PathKeyedMap(normalizeMapKey);
|
|
6067
6901
|
var RENDER_TIMEOUT_MS = 3e4;
|
|
@@ -6095,10 +6929,10 @@ function resolveTemplateSource(sourceRef, chartRoot, realChartRoot) {
|
|
|
6095
6929
|
if (!isWithin2(chartRoot, candidate))
|
|
6096
6930
|
return null;
|
|
6097
6931
|
try {
|
|
6098
|
-
if (!
|
|
6932
|
+
if (!fs12.lstatSync(candidate).isFile())
|
|
6099
6933
|
return null;
|
|
6100
|
-
const root = realChartRoot ??
|
|
6101
|
-
if (!isWithin2(root,
|
|
6934
|
+
const root = realChartRoot ?? fs12.realpathSync(chartRoot);
|
|
6935
|
+
if (!isWithin2(root, fs12.realpathSync(candidate)))
|
|
6102
6936
|
return null;
|
|
6103
6937
|
} catch {
|
|
6104
6938
|
return null;
|
|
@@ -6107,7 +6941,7 @@ function resolveTemplateSource(sourceRef, chartRoot, realChartRoot) {
|
|
|
6107
6941
|
}
|
|
6108
6942
|
function canonicalChartRoot(chartRoot) {
|
|
6109
6943
|
try {
|
|
6110
|
-
return
|
|
6944
|
+
return fs12.realpathSync(chartRoot);
|
|
6111
6945
|
} catch {
|
|
6112
6946
|
return chartRoot;
|
|
6113
6947
|
}
|
|
@@ -6342,7 +7176,7 @@ function collectRenderedFiles(root) {
|
|
|
6342
7176
|
const dir = stack.pop();
|
|
6343
7177
|
let entries;
|
|
6344
7178
|
try {
|
|
6345
|
-
entries =
|
|
7179
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
6346
7180
|
} catch {
|
|
6347
7181
|
continue;
|
|
6348
7182
|
}
|
|
@@ -6381,7 +7215,7 @@ function readRenderedTree(outputDir, chartRoot) {
|
|
|
6381
7215
|
for (const renderedPath of walk2.files) {
|
|
6382
7216
|
let content;
|
|
6383
7217
|
try {
|
|
6384
|
-
content =
|
|
7218
|
+
content = fs12.readFileSync(renderedPath, "utf-8");
|
|
6385
7219
|
} catch {
|
|
6386
7220
|
unreadable += 1;
|
|
6387
7221
|
continue;
|
|
@@ -6500,7 +7334,7 @@ function logRenderPass(filePath, chartRoot, startedAt, metadata) {
|
|
|
6500
7334
|
metadata: { chartRoot, ...metadata }
|
|
6501
7335
|
});
|
|
6502
7336
|
}
|
|
6503
|
-
function discardScratchDir(outputDir, filePath, remove = (target) =>
|
|
7337
|
+
function discardScratchDir(outputDir, filePath, remove = (target) => fs12.rmSync(target, { recursive: true, force: true })) {
|
|
6504
7338
|
try {
|
|
6505
7339
|
remove(outputDir);
|
|
6506
7340
|
} catch (error) {
|
|
@@ -6521,7 +7355,7 @@ async function renderAndValidate(chartRoot, cwd, filePath) {
|
|
|
6521
7355
|
const helmCmd = await resolveAvailableOrInstall(helm2, "helm", cwd);
|
|
6522
7356
|
if (!helmCmd)
|
|
6523
7357
|
return helmUnavailableResult(cwd);
|
|
6524
|
-
const outputDir =
|
|
7358
|
+
const outputDir = fs12.mkdtempSync(path22.join(os.tmpdir(), "pi-lens-helm-render-"));
|
|
6525
7359
|
try {
|
|
6526
7360
|
const render = await safeSpawnAsync(helmCmd, ["template", "pi-lens-render", chartRoot, "--output-dir", outputDir], {
|
|
6527
7361
|
cwd,
|
|
@@ -6842,9 +7676,30 @@ function normalizeKtlintResults(parsed) {
|
|
|
6842
7676
|
}
|
|
6843
7677
|
return null;
|
|
6844
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
|
+
}
|
|
6845
7700
|
function parseKtlintOutput(raw, filePath, cwd) {
|
|
6846
7701
|
try {
|
|
6847
|
-
const parsed =
|
|
7702
|
+
const parsed = parseReporterDocument(raw);
|
|
6848
7703
|
if (!parsed)
|
|
6849
7704
|
return null;
|
|
6850
7705
|
const autofix = getAutofixCapability("ktlint");
|
|
@@ -6855,15 +7710,15 @@ function parseKtlintOutput(raw, filePath, cwd) {
|
|
|
6855
7710
|
continue;
|
|
6856
7711
|
for (const err of result.errors ?? []) {
|
|
6857
7712
|
diagnostics.push({
|
|
6858
|
-
id: `ktlint-${err.
|
|
6859
|
-
message: `[${err.
|
|
7713
|
+
id: `ktlint-${err.rule}-${err.line}-${err.column}`,
|
|
7714
|
+
message: `[${err.rule}] ${err.message}`,
|
|
6860
7715
|
filePath,
|
|
6861
7716
|
line: err.line,
|
|
6862
|
-
column: err.
|
|
7717
|
+
column: err.column,
|
|
6863
7718
|
severity: "warning",
|
|
6864
7719
|
semantic: "warning",
|
|
6865
7720
|
tool: "ktlint",
|
|
6866
|
-
rule: err.
|
|
7721
|
+
rule: err.rule,
|
|
6867
7722
|
fixable: true,
|
|
6868
7723
|
autoFixAvailable: autofix?.safePipelineAutofix ?? false,
|
|
6869
7724
|
fixKind: autofix?.fixKind === "none" ? void 0 : autofix?.fixKind
|
|
@@ -7037,16 +7892,6 @@ async function demoteInferredProjectSweepResults(results, cwd, service, signal)
|
|
|
7037
7892
|
return out;
|
|
7038
7893
|
}
|
|
7039
7894
|
|
|
7040
|
-
// dist/clients/dispatch/runners/utils.js
|
|
7041
|
-
import * as fs12 from "node:fs";
|
|
7042
|
-
function readFileContent(filePath) {
|
|
7043
|
-
try {
|
|
7044
|
-
return fs12.readFileSync(filePath, "utf-8");
|
|
7045
|
-
} catch {
|
|
7046
|
-
return void 0;
|
|
7047
|
-
}
|
|
7048
|
-
}
|
|
7049
|
-
|
|
7050
7895
|
// dist/clients/dispatch/runners/lsp.js
|
|
7051
7896
|
var LSP_SPAWN_BUDGET_MS = RUNTIME_CONFIG.pipeline.lspSpawnBudgetMs;
|
|
7052
7897
|
var LSP_DIAGNOSTICS_WAIT_MS = 2500;
|
|
@@ -7083,13 +7928,23 @@ var lspRunner = {
|
|
|
7083
7928
|
}
|
|
7084
7929
|
const lspService = getLSPService();
|
|
7085
7930
|
if (!lspService.supportsLSP(ctx.filePath)) {
|
|
7086
|
-
|
|
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
|
+
};
|
|
7087
7941
|
}
|
|
7088
7942
|
let lspDiags = [];
|
|
7089
7943
|
let serverFailed = false;
|
|
7090
7944
|
let lspClientReady = true;
|
|
7091
7945
|
let diagnosticsInconclusive = false;
|
|
7092
7946
|
let inconclusiveServerIds = [];
|
|
7947
|
+
let primaryUnavailable;
|
|
7093
7948
|
let unconfirmedServerIds = [];
|
|
7094
7949
|
let deferredServerIds = [];
|
|
7095
7950
|
let usedWarmAttach = false;
|
|
@@ -7127,6 +7982,15 @@ var lspRunner = {
|
|
|
7127
7982
|
lspDiags = touched.diags;
|
|
7128
7983
|
diagnosticsInconclusive = touched.inconclusive === true;
|
|
7129
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
|
+
}
|
|
7130
7994
|
unconfirmedServerIds = [
|
|
7131
7995
|
.../* @__PURE__ */ new Set([
|
|
7132
7996
|
...touchCoverageGap(touched),
|
|
@@ -7178,10 +8042,20 @@ var lspRunner = {
|
|
|
7178
8042
|
};
|
|
7179
8043
|
}
|
|
7180
8044
|
if (!lspClientReady) {
|
|
7181
|
-
return {
|
|
8045
|
+
return {
|
|
8046
|
+
status: "skipped",
|
|
8047
|
+
diagnostics: [],
|
|
8048
|
+
semantic: "none",
|
|
8049
|
+
primaryUnavailableCause: "unstarted"
|
|
8050
|
+
};
|
|
7182
8051
|
}
|
|
7183
8052
|
if (diagnosticsInconclusive && lspDiags.length === 0) {
|
|
7184
|
-
return {
|
|
8053
|
+
return {
|
|
8054
|
+
status: "skipped",
|
|
8055
|
+
diagnostics: [],
|
|
8056
|
+
semantic: "none",
|
|
8057
|
+
...primaryUnavailable
|
|
8058
|
+
};
|
|
7185
8059
|
}
|
|
7186
8060
|
if (lspDiags.length === 0) {
|
|
7187
8061
|
if (deferredServerIds.length > 0) {
|
|
@@ -7246,7 +8120,15 @@ var lspRunner = {
|
|
|
7246
8120
|
}));
|
|
7247
8121
|
}
|
|
7248
8122
|
const diagnostics = convertLspDiagnostics(validLspDiags, diagnosticPath, { fixSuggestionByIndex });
|
|
7249
|
-
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
|
+
}
|
|
7250
8132
|
const hasErrors = keptDiagnostics.some((d) => d.semantic === "blocking");
|
|
7251
8133
|
const resultSemantic = hasErrors ? "blocking" : keptDiagnostics.length > 0 ? "warning" : "none";
|
|
7252
8134
|
return {
|
|
@@ -7261,7 +8143,8 @@ var lspRunner = {
|
|
|
7261
8143
|
},
|
|
7262
8144
|
...deferredServerIds.length > 0 && {
|
|
7263
8145
|
deferredServerIds: [...deferredServerIds]
|
|
7264
|
-
}
|
|
8146
|
+
},
|
|
8147
|
+
...outOfEditScope.length > 0 && { outOfEditScope }
|
|
7265
8148
|
};
|
|
7266
8149
|
}
|
|
7267
8150
|
};
|
|
@@ -7791,13 +8674,9 @@ var phpLintRunner = {
|
|
|
7791
8674
|
skipTestFiles: false,
|
|
7792
8675
|
async run(ctx) {
|
|
7793
8676
|
const cwd = resolveRunnerCwd(ctx, "php-lint");
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
}
|
|
7797
|
-
const cmd = php.getCommand(cwd);
|
|
7798
|
-
if (!cmd) {
|
|
8677
|
+
const cmd = ctx.analysisRootMode === "adopted" ? resolveAdoptedRootCommand("php", ctx, cwd) : await php.isAvailableAsync(cwd) ? php.getCommand(cwd) : null;
|
|
8678
|
+
if (!cmd)
|
|
7799
8679
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
7800
|
-
}
|
|
7801
8680
|
const absPath = path30.resolve(cwd, ctx.filePath);
|
|
7802
8681
|
const result = await safeSpawnAsync(cmd, ["-l", absPath], {
|
|
7803
8682
|
timeout: 15e3,
|
|
@@ -8301,7 +9180,7 @@ var pyrightRunner = {
|
|
|
8301
9180
|
cmd = installedPath;
|
|
8302
9181
|
}
|
|
8303
9182
|
if (!cmd) {
|
|
8304
|
-
const { findCommandAsync } = await import("./chunk-
|
|
9183
|
+
const { findCommandAsync } = await import("./chunk-LLJNQKQW.js");
|
|
8305
9184
|
const foundCmd = await findCommandAsync("pyright");
|
|
8306
9185
|
if (foundCmd)
|
|
8307
9186
|
cmd = foundCmd;
|
|
@@ -8904,6 +9783,7 @@ var spotbugs_default = spotbugsRunner;
|
|
|
8904
9783
|
import * as fs15 from "node:fs";
|
|
8905
9784
|
import * as path36 from "node:path";
|
|
8906
9785
|
var shellcheck = createAvailabilityChecker("shellcheck", ".exe");
|
|
9786
|
+
var SHELLCHECK_EXIT_CODES = { ran: [1] };
|
|
8907
9787
|
var SHELLCHECK_DIALECTS = [
|
|
8908
9788
|
"sh",
|
|
8909
9789
|
"bash",
|
|
@@ -9027,7 +9907,10 @@ var shellcheckRunner = {
|
|
|
9027
9907
|
skipReason: "covered-by-primary",
|
|
9028
9908
|
// WHO claimed (#3968 F2): declared (the row's own covers, gated
|
|
9029
9909
|
// on the custom row's own command) or builtin-fact.
|
|
9030
|
-
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 }
|
|
9031
9914
|
};
|
|
9032
9915
|
}
|
|
9033
9916
|
const dialectInfo = resolveShellFileDialect(ctx.filePath);
|
|
@@ -9062,20 +9945,52 @@ var shellcheckRunner = {
|
|
|
9062
9945
|
if (result.status === 0 && !result.stdout?.trim()) {
|
|
9063
9946
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9064
9947
|
}
|
|
9065
|
-
const raw = result.stdout
|
|
9066
|
-
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;
|
|
9067
9952
|
return finishParsedRun({
|
|
9068
9953
|
tool: "shellcheck",
|
|
9069
9954
|
ctx,
|
|
9070
9955
|
result,
|
|
9071
|
-
diagnostics
|
|
9956
|
+
diagnostics: parsed.diagnostics
|
|
9072
9957
|
});
|
|
9073
9958
|
}
|
|
9074
9959
|
};
|
|
9075
9960
|
var shellcheck_default = shellcheckRunner;
|
|
9076
9961
|
|
|
9077
9962
|
// dist/clients/dispatch/runners/fish-indent.js
|
|
9963
|
+
import { resolve as resolve32 } from "node:path";
|
|
9078
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" };
|
|
9079
9994
|
var fishIndentRunner = {
|
|
9080
9995
|
id: "fish-indent",
|
|
9081
9996
|
appliesTo: ["fish"],
|
|
@@ -9083,12 +9998,27 @@ var fishIndentRunner = {
|
|
|
9083
9998
|
skipTestFiles: false,
|
|
9084
9999
|
async run(ctx) {
|
|
9085
10000
|
const cwd = resolveRunnerCwd(ctx, "fish-indent");
|
|
9086
|
-
const
|
|
9087
|
-
if (!available)
|
|
9088
|
-
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
9089
|
-
const cmd = fishIndent.getCommand(cwd);
|
|
10001
|
+
const cmd = ctx.analysisRootMode === "adopted" ? resolveAdoptedRootCommand("fish_indent", ctx, cwd) : await fishIndent.isAvailableAsync(cwd) ? fishIndent.getCommand(cwd) : null;
|
|
9090
10002
|
if (!cmd)
|
|
9091
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
|
+
}
|
|
9092
10022
|
const result = await safeSpawnAsync(cmd, ["--check", ctx.filePath], {
|
|
9093
10023
|
timeout: 1e4,
|
|
9094
10024
|
cwd
|
|
@@ -9096,7 +10026,12 @@ var fishIndentRunner = {
|
|
|
9096
10026
|
if (result.status === 0) {
|
|
9097
10027
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9098
10028
|
}
|
|
9099
|
-
|
|
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)));
|
|
9100
10035
|
if (stderrLine) {
|
|
9101
10036
|
const lineMatch = stderrLine.match(/\(line\s+(\d+)\)/);
|
|
9102
10037
|
const line = lineMatch ? Number(lineMatch[1]) : 1;
|
|
@@ -9113,10 +10048,7 @@ var fishIndentRunner = {
|
|
|
9113
10048
|
rule: "fish-indent-parse-error"
|
|
9114
10049
|
}
|
|
9115
10050
|
];
|
|
9116
|
-
return findingsResult(diagnostics2,
|
|
9117
|
-
status: "failed",
|
|
9118
|
-
semantic: "blocking"
|
|
9119
|
-
});
|
|
10051
|
+
return findingsResult(diagnostics2, BLOCKING_VERDICT);
|
|
9120
10052
|
}
|
|
9121
10053
|
const diagnostics = [
|
|
9122
10054
|
{
|
|
@@ -9167,6 +10099,12 @@ var shfmtRunner = {
|
|
|
9167
10099
|
timeout: 1e4,
|
|
9168
10100
|
cwd
|
|
9169
10101
|
});
|
|
10102
|
+
const didNotRun = skipUnlessToolRan("shfmt", {
|
|
10103
|
+
result,
|
|
10104
|
+
output: `${result.stdout ?? ""}${result.stderr ?? ""}`
|
|
10105
|
+
});
|
|
10106
|
+
if (didNotRun)
|
|
10107
|
+
return didNotRun;
|
|
9170
10108
|
if (result.status === 0) {
|
|
9171
10109
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
9172
10110
|
}
|
|
@@ -9748,7 +10686,10 @@ var taploRunner = {
|
|
|
9748
10686
|
// an unexplained empty output on the delivery surfaces
|
|
9749
10687
|
// (defect shape 10). F2 adds the claim's provenance beside it.
|
|
9750
10688
|
skipReason: "covered-by-primary",
|
|
9751
|
-
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 }
|
|
9752
10693
|
};
|
|
9753
10694
|
}
|
|
9754
10695
|
let cmd = localBinPath(findLocalBinUpwards("taplo", cwd)) ?? null;
|
|
@@ -10596,11 +11537,6 @@ function defaultFixSuggestion2(defectClass, ruleId) {
|
|
|
10596
11537
|
}
|
|
10597
11538
|
return "Refactor this pattern to a safer, explicit form matching project conventions.";
|
|
10598
11539
|
}
|
|
10599
|
-
function isLineInModifiedRanges(line, ranges) {
|
|
10600
|
-
if (!ranges || ranges.length === 0)
|
|
10601
|
-
return true;
|
|
10602
|
-
return ranges.some((r) => line >= r.start && line <= r.end);
|
|
10603
|
-
}
|
|
10604
11540
|
function getTotalLinesChanged(ranges) {
|
|
10605
11541
|
if (!ranges || ranges.length === 0)
|
|
10606
11542
|
return 0;
|
|
@@ -10725,19 +11661,20 @@ var treeSitterRunner = {
|
|
|
10725
11661
|
const contentFromFacts = ctx.facts.getFileFact(filePath, "file.content");
|
|
10726
11662
|
const contentOverride = contentFromFacts !== void 0 && contentFromFacts !== null ? contentFromFacts : void 0;
|
|
10727
11663
|
const diagnostics = [];
|
|
11664
|
+
const withheld = [];
|
|
11665
|
+
let queryRunFailed = false;
|
|
10728
11666
|
try {
|
|
10729
11667
|
const found = await client.runQueriesOnFile(effectiveQueries, filePath, languageId, { maxResults: 10 }, contentOverride);
|
|
10730
11668
|
for (const { queryDef: query, match } of found) {
|
|
10731
11669
|
const { line, column } = match;
|
|
10732
11670
|
const isSeverityBlocking = query.severity === "error" || query.inline_tier === "blocking" || SILENT_ERROR_QUERY_IDS.has(query.id);
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
}
|
|
11671
|
+
const endLine = line + (match.matchedText.match(/\n/g)?.length ?? 0);
|
|
11672
|
+
const outOfScope = ctx.blockingOnly && isSeverityBlocking && !spanOverlapsModifiedRanges(line, endLine, ctx.modifiedRanges);
|
|
10736
11673
|
const semantic = query.severity === "error" ? "blocking" : query.severity === "warning" ? "warning" : "none";
|
|
10737
11674
|
const defectClass = query.defect_class ?? classifyDefect(query.id, "tree-sitter", query.message);
|
|
10738
11675
|
const suggestion = query.has_fix && query.fix_action ? `${query.fix_action} this statement` : semantic === "blocking" ? defaultFixSuggestion2(defectClass, query.id) : void 0;
|
|
10739
11676
|
const hasSuggestedFix = !!query.has_fix;
|
|
10740
|
-
diagnostics.push({
|
|
11677
|
+
(outOfScope ? withheld : diagnostics).push({
|
|
10741
11678
|
id: `tree-sitter:${query.id}:${line}`,
|
|
10742
11679
|
message: query.message.replace(/\{\{(\w+)\}\}/g, (_, name) => match.captures[name]?.trim() ?? `{{${name}}}`),
|
|
10743
11680
|
filePath,
|
|
@@ -10759,6 +11696,7 @@ var treeSitterRunner = {
|
|
|
10759
11696
|
});
|
|
10760
11697
|
}
|
|
10761
11698
|
} catch (err) {
|
|
11699
|
+
queryRunFailed = true;
|
|
10762
11700
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10763
11701
|
if (classifyTreeSitterWasmError(err) === "abort") {
|
|
10764
11702
|
markTreeSitterWasmAborted();
|
|
@@ -10818,6 +11756,10 @@ var treeSitterRunner = {
|
|
|
10818
11756
|
} catch {
|
|
10819
11757
|
}
|
|
10820
11758
|
}
|
|
11759
|
+
const observationExtras = {
|
|
11760
|
+
...withheld.length > 0 && { outOfEditScope: withheld },
|
|
11761
|
+
...queryRunFailed && { inconclusive: true }
|
|
11762
|
+
};
|
|
10821
11763
|
if (diagnostics.length === 0) {
|
|
10822
11764
|
if (!isTreeSitterWasmAborted() && !client.getLanguage(languageId)) {
|
|
10823
11765
|
logTreeSitter({
|
|
@@ -10827,7 +11769,11 @@ var treeSitterRunner = {
|
|
|
10827
11769
|
reason: "grammar_unavailable",
|
|
10828
11770
|
status: "skipped"
|
|
10829
11771
|
});
|
|
10830
|
-
return {
|
|
11772
|
+
return {
|
|
11773
|
+
status: "skipped",
|
|
11774
|
+
diagnostics: [],
|
|
11775
|
+
semantic: "none"
|
|
11776
|
+
};
|
|
10831
11777
|
}
|
|
10832
11778
|
logTreeSitter({
|
|
10833
11779
|
phase: "runner_complete",
|
|
@@ -10839,7 +11785,12 @@ var treeSitterRunner = {
|
|
|
10839
11785
|
queryCount: languageQueries.length,
|
|
10840
11786
|
effectiveQueryCount: effectiveQueries.length
|
|
10841
11787
|
});
|
|
10842
|
-
return {
|
|
11788
|
+
return {
|
|
11789
|
+
status: "succeeded",
|
|
11790
|
+
diagnostics: [],
|
|
11791
|
+
semantic: "none",
|
|
11792
|
+
...observationExtras
|
|
11793
|
+
};
|
|
10843
11794
|
}
|
|
10844
11795
|
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
|
|
10845
11796
|
const blockingCount = diagnostics.filter((d) => d.semantic === "blocking").length;
|
|
@@ -10853,10 +11804,13 @@ var treeSitterRunner = {
|
|
|
10853
11804
|
queryCount: languageQueries.length,
|
|
10854
11805
|
effectiveQueryCount: effectiveQueries.length
|
|
10855
11806
|
});
|
|
10856
|
-
return
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
11807
|
+
return {
|
|
11808
|
+
...findingsResult(diagnostics, {
|
|
11809
|
+
status: hasBlocking ? "failed" : "succeeded",
|
|
11810
|
+
semantic: hasBlocking ? "blocking" : "warning"
|
|
11811
|
+
}),
|
|
11812
|
+
...observationExtras
|
|
11813
|
+
};
|
|
10860
11814
|
}
|
|
10861
11815
|
};
|
|
10862
11816
|
var tree_sitter_default = treeSitterRunner;
|
|
@@ -11267,8 +12221,6 @@ function isTestSuiteOrganizer(calls) {
|
|
|
11267
12221
|
// dist/clients/dispatch/rules/high-complexity.js
|
|
11268
12222
|
var DEFAULT_HIGH_COMPLEXITY_THRESHOLD = 15;
|
|
11269
12223
|
var DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD = 6;
|
|
11270
|
-
var ccThreshold = DEFAULT_HIGH_COMPLEXITY_THRESHOLD;
|
|
11271
|
-
var depthThreshold = DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD;
|
|
11272
12224
|
var highComplexityRule = {
|
|
11273
12225
|
id: "high-complexity",
|
|
11274
12226
|
requires: ["file.functionSummaries"],
|
|
@@ -11279,12 +12231,12 @@ var highComplexityRule = {
|
|
|
11279
12231
|
const fns = store.getFileFact(ctx.filePath, "file.functionSummaries") ?? [];
|
|
11280
12232
|
const diagnostics = [];
|
|
11281
12233
|
const configuredCcThreshold = ctx.projectConfig?.rules["high-complexity"]?.threshold;
|
|
11282
|
-
const activeCcThreshold = configuredCcThreshold ??
|
|
12234
|
+
const activeCcThreshold = configuredCcThreshold ?? DEFAULT_HIGH_COMPLEXITY_THRESHOLD;
|
|
11283
12235
|
for (const f of fns) {
|
|
11284
12236
|
if (isTestSuiteOrganizer(f.outgoingCalls))
|
|
11285
12237
|
continue;
|
|
11286
12238
|
const ccBreached = f.cyclomaticComplexity >= activeCcThreshold;
|
|
11287
|
-
const depthBreached = f.maxNestingDepth >=
|
|
12239
|
+
const depthBreached = f.maxNestingDepth >= DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD;
|
|
11288
12240
|
if (!ccBreached && !depthBreached)
|
|
11289
12241
|
continue;
|
|
11290
12242
|
const parts = [];
|
|
@@ -11310,7 +12262,6 @@ var highComplexityRule = {
|
|
|
11310
12262
|
|
|
11311
12263
|
// dist/clients/dispatch/rules/high-fan-out.js
|
|
11312
12264
|
var DEFAULT_HIGH_FAN_OUT_THRESHOLD = 20;
|
|
11313
|
-
var fanOutThreshold = DEFAULT_HIGH_FAN_OUT_THRESHOLD;
|
|
11314
12265
|
var highFanOutRule = {
|
|
11315
12266
|
id: "high-fan-out",
|
|
11316
12267
|
requires: ["file.functionSummaries"],
|
|
@@ -11321,7 +12272,7 @@ var highFanOutRule = {
|
|
|
11321
12272
|
const fns = store.getFileFact(ctx.filePath, "file.functionSummaries") ?? [];
|
|
11322
12273
|
const diagnostics = [];
|
|
11323
12274
|
const configuredFanOutThreshold = ctx.projectConfig?.rules["high-fan-out"]?.threshold;
|
|
11324
|
-
const activeFanOutThreshold = configuredFanOutThreshold ??
|
|
12275
|
+
const activeFanOutThreshold = configuredFanOutThreshold ?? DEFAULT_HIGH_FAN_OUT_THRESHOLD;
|
|
11325
12276
|
for (const f of fns) {
|
|
11326
12277
|
if (isTestSuiteOrganizer(f.outgoingCalls))
|
|
11327
12278
|
continue;
|
|
@@ -11680,6 +12631,8 @@ function applyProjectLensConfig(cwd) {
|
|
|
11680
12631
|
return loadPiLensProjectConfig(cwd);
|
|
11681
12632
|
}
|
|
11682
12633
|
var sessionFacts = new FactStore("dispatch");
|
|
12634
|
+
var preEditCaptureFacts = new FactStore("pre-edit-capture");
|
|
12635
|
+
var preEditCapturesInFlight = /* @__PURE__ */ new Map();
|
|
11683
12636
|
setFactStoreEvictionReporter((subject, axis, reason) => {
|
|
11684
12637
|
if (axis === "pinned-over-budget") {
|
|
11685
12638
|
recordDegradationOnce({
|
|
@@ -11861,12 +12814,16 @@ function resetDispatchBaselines(cwd) {
|
|
|
11861
12814
|
resetAstGrepNapiLoadState();
|
|
11862
12815
|
resetTreeSitterClientLoadState();
|
|
11863
12816
|
sessionFacts.clearAll();
|
|
12817
|
+
for (const controller of preEditCapturesInFlight.values())
|
|
12818
|
+
controller.abort();
|
|
12819
|
+
preEditCaptureFacts.clearAll();
|
|
11864
12820
|
resetSessionSlopScore();
|
|
11865
12821
|
clearCoverageNoticeState();
|
|
11866
12822
|
clearReviewGraphWorkspaceCache();
|
|
11867
12823
|
clearReverseDepsIndexCache();
|
|
11868
12824
|
clearModuleGraphCache();
|
|
11869
|
-
|
|
12825
|
+
resetCascadeUnansweredPrimariesDelivered();
|
|
12826
|
+
resetCascadePendingNeighbors();
|
|
11870
12827
|
primaryFilesThisTurn.clear();
|
|
11871
12828
|
cascadeSessionStats = {
|
|
11872
12829
|
runs: 0,
|
|
@@ -11882,7 +12839,6 @@ var cascadeSessionStats = {
|
|
|
11882
12839
|
diagnosticsSurfaced: 0,
|
|
11883
12840
|
coldSnapshotTouches: 0
|
|
11884
12841
|
};
|
|
11885
|
-
var recentlyCleanNeighborCache = /* @__PURE__ */ new Map();
|
|
11886
12842
|
var primaryFilesThisTurn = /* @__PURE__ */ new Set();
|
|
11887
12843
|
var MAX_PER_FILE = RUNTIME_CONFIG.pipeline.cascadeMaxDiagnosticsPerFile;
|
|
11888
12844
|
var MAX_FILES = RUNTIME_CONFIG.pipeline.cascadeMaxFiles;
|
|
@@ -11910,8 +12866,16 @@ var CASCADE_GRAPH_KINDS = /* @__PURE__ */ new Set([
|
|
|
11910
12866
|
"ruby",
|
|
11911
12867
|
"cxx"
|
|
11912
12868
|
]);
|
|
12869
|
+
var IMPLICIT_SCOPE_NEIGHBOR_CAP = MAX_FILES * 2;
|
|
11913
12870
|
async function dispatchLintWithResult(filePath, cwd, pi, modifiedRanges, logContext, options) {
|
|
11914
|
-
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;
|
|
11915
12879
|
sessionFacts.clearFileFactsFor(ctx.filePath);
|
|
11916
12880
|
try {
|
|
11917
12881
|
const kind = ctx.kind;
|
|
@@ -12042,14 +13006,17 @@ function enforceWarmWordIndexLruCap() {
|
|
|
12042
13006
|
return;
|
|
12043
13007
|
}
|
|
12044
13008
|
}
|
|
13009
|
+
function usableWarmWordIndex(index) {
|
|
13010
|
+
return index?.forward ? index : void 0;
|
|
13011
|
+
}
|
|
12045
13012
|
function acquireWarmWordIndex(cwd) {
|
|
12046
13013
|
const key2 = path50.resolve(cwd);
|
|
12047
13014
|
let entry = warmWordIndexes.get(key2);
|
|
12048
13015
|
if (!entry) {
|
|
12049
13016
|
const snapshot = loadProjectSnapshot(key2);
|
|
12050
|
-
const index = deserializeWordIndex(snapshot?.wordIndex) ?? void 0;
|
|
13017
|
+
const index = usableWarmWordIndex(deserializeWordIndex(snapshot?.wordIndex) ?? void 0);
|
|
12051
13018
|
entry = {
|
|
12052
|
-
index
|
|
13019
|
+
index,
|
|
12053
13020
|
timer: void 0,
|
|
12054
13021
|
leases: 0,
|
|
12055
13022
|
lastUsedAt: Date.now(),
|
|
@@ -12077,6 +13044,26 @@ function acquireWarmWordIndex(cwd) {
|
|
|
12077
13044
|
}
|
|
12078
13045
|
};
|
|
12079
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);
|
|
12080
13067
|
function _resetWarmWordIndexCacheForTests() {
|
|
12081
13068
|
for (const entry of warmWordIndexes.values())
|
|
12082
13069
|
clearWarmWordIndexTimer(entry);
|
|
@@ -12139,7 +13126,13 @@ async function warmLspForFile(absPath, host) {
|
|
|
12139
13126
|
clientScope: "primary",
|
|
12140
13127
|
maxClientWaitMs: WARMUP_CLIENT_WAIT_MS,
|
|
12141
13128
|
maxDiagnosticsWaitMs: WARMUP_DIAGNOSTICS_WAIT_MS,
|
|
12142
|
-
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
|
|
12143
13136
|
});
|
|
12144
13137
|
} catch {
|
|
12145
13138
|
}
|
|
@@ -12154,6 +13147,7 @@ async function analyzeFile(filePath, cwd, options = {}) {
|
|
|
12154
13147
|
const start = Date.now();
|
|
12155
13148
|
const result = await dispatchLintWithResult(absPath, cwd, host, void 0, void 0, {
|
|
12156
13149
|
blockingOnly: options.blockingOnly ?? false,
|
|
13150
|
+
analysisRootMode: resolveAnalysisRoot(absPath, cwd),
|
|
12157
13151
|
// #3791: this is a pull surface. Each call is an independent question,
|
|
12158
13152
|
// so the synthetic coverage notice must come back on every call rather
|
|
12159
13153
|
// than being latched once per session by the dispatcher — otherwise a
|
|
@@ -12259,6 +13253,18 @@ export {
|
|
|
12259
13253
|
CacheManager,
|
|
12260
13254
|
getDiagnosticTracker,
|
|
12261
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,
|
|
12262
13268
|
getToolPlan,
|
|
12263
13269
|
resetObservedRunnerLatency,
|
|
12264
13270
|
requeueRunnerFindings,
|
|
@@ -12266,25 +13272,28 @@ export {
|
|
|
12266
13272
|
dropStaleRunnerFindings,
|
|
12267
13273
|
resetPendingRunnerFindings,
|
|
12268
13274
|
pendingRunnerFindingsSize,
|
|
12269
|
-
|
|
13275
|
+
laneCopyStandsFor,
|
|
12270
13276
|
DELTA_UNUSED_PROMOTION_NOTE,
|
|
12271
13277
|
formatDiagnostics,
|
|
12272
13278
|
createDispatchContext,
|
|
12273
13279
|
getLatencyReports,
|
|
12274
13280
|
cascadeSettleWaitMs,
|
|
12275
|
-
convertLspDiagnostics,
|
|
12276
|
-
applyFindingPolicy,
|
|
12277
|
-
loadProjectRulePolicyMap,
|
|
12278
|
-
inlineBlockerIdentities,
|
|
12279
|
-
applyPushedFindingPolicy,
|
|
12280
|
-
applyLspFindingPolicy,
|
|
12281
|
-
filterFindingsByDisposition,
|
|
12282
13281
|
markUnreconciledFindings,
|
|
12283
13282
|
formatCacheAgeLabel,
|
|
13283
|
+
dispositionSuppressedLine,
|
|
12284
13284
|
admitsProjectWideFindings,
|
|
13285
|
+
formatCascadeNeighborDiagnostics,
|
|
13286
|
+
composeCascadeSection,
|
|
12285
13287
|
cascadeCarrySuffix,
|
|
13288
|
+
markCascadeUnansweredPrimariesDelivered,
|
|
13289
|
+
renderCascadeResult,
|
|
13290
|
+
cascadeStillPresentSince,
|
|
13291
|
+
recordDeliveredCascadeNeighbor,
|
|
13292
|
+
forgetCascadePendingNeighbor,
|
|
13293
|
+
listCascadePendingNeighbors,
|
|
12286
13294
|
logCascade,
|
|
12287
13295
|
resetCascadeTierSessionState,
|
|
13296
|
+
peekOutstandingCascadeTouches,
|
|
12288
13297
|
loadSg,
|
|
12289
13298
|
canHandle,
|
|
12290
13299
|
getLang,
|