@herbertgao/pi-extensions 2026.10.1 → 2026.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (934) hide show
  1. package/README.md +14 -17
  2. package/THIRD_PARTY_NOTICES.md +2 -2
  3. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +2 -2
  4. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +2 -2
  5. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +1 -1
  6. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +1 -1
  7. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +2 -2
  8. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +1 -1
  9. package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +21 -21
  10. package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
  11. package/node_modules/@dietrichgebert/ponytail/AGENTS.md +21 -21
  12. package/node_modules/@dietrichgebert/ponytail/README.md +68 -72
  13. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +7 -0
  14. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +30 -30
  15. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-map.js +103 -0
  16. package/node_modules/@dietrichgebert/ponytail/package.json +2 -2
  17. package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +33 -101
  18. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +89 -32
  19. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +13 -12
  20. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +17 -16
  21. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +9 -10
  22. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +96 -57
  23. package/node_modules/{remote-pi → @herbertgao/pi-agency}/LICENSE +1 -1
  24. package/node_modules/@herbertgao/pi-agency/README.md +40 -0
  25. package/node_modules/@herbertgao/pi-agency/package.json +53 -0
  26. package/node_modules/@herbertgao/pi-agency/src/index.ts +441 -0
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +12 -12
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +30 -6
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +15 -9
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +27 -9
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +4 -1
  32. package/node_modules/@herbertgao/pi-cc-extensions/package.json +2 -2
  33. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
  34. package/node_modules/@herbertgao/pi-subagents/README.md +1 -1
  35. package/node_modules/@herbertgao/pi-subagents/package.json +4 -5
  36. package/node_modules/@herbertgao/pi-subagents/src/index.ts +1 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +1 -1
  38. package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +48 -72
  39. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +1 -1
  40. package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +15 -6
  41. package/node_modules/@herbertgao/pi-subagents/src/workflow/collisions.ts +4 -1
  42. package/node_modules/@herbertgao/pi-subagents/src/workflow/json-schema.ts +9 -8
  43. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +6 -1
  44. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +2 -2
  45. package/node_modules/@narumitw/pi-caffeinate/package.json +3 -3
  46. package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +13 -1
  47. package/node_modules/@tifan/pi-mermaid-open/package.json +5 -1
  48. package/node_modules/@tifan/pi-mermaid-open/src/index.ts +26 -9
  49. package/node_modules/@tifan/pi-recap/package.json +1 -1
  50. package/node_modules/@tifan/pi-recap/src/index.ts +104 -20
  51. package/node_modules/@tifan/pi-recap/src/models.ts +46 -4
  52. package/node_modules/pi-antigravity/README.md +23 -2
  53. package/node_modules/pi-antigravity/package.json +5 -3
  54. package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +3 -2
  55. package/node_modules/pi-antigravity/src/features/generate-image.ts +72 -0
  56. package/node_modules/pi-antigravity/src/features/google-search.ts +71 -0
  57. package/node_modules/pi-antigravity/src/image/image.ts +86 -47
  58. package/node_modules/pi-antigravity/src/image/native.ts +69 -0
  59. package/node_modules/pi-antigravity/src/index.ts +52 -137
  60. package/node_modules/pi-antigravity/src/search/search.ts +130 -31
  61. package/node_modules/pi-antigravity/src/stream/stream.ts +162 -113
  62. package/node_modules/pi-antigravity/src/types/enums.ts +1 -0
  63. package/node_modules/pi-antigravity/src/types/types.ts +1 -1
  64. package/node_modules/pi-antigravity/src/utils/security.ts +47 -1
  65. package/node_modules/pi-antigravity/src/utils/util.ts +38 -6
  66. package/node_modules/pi-lens/CHANGELOG.md +1159 -0
  67. package/node_modules/pi-lens/README.md +116 -25
  68. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +6 -2
  69. package/node_modules/pi-lens/dist/chunk-2BEMIWEW.js +51 -0
  70. package/node_modules/pi-lens/dist/chunk-2EECBNC5.js +89 -0
  71. package/node_modules/pi-lens/dist/chunk-2FQ62SPM.js +83 -0
  72. package/node_modules/pi-lens/dist/chunk-2UMYMRI3.js +118 -0
  73. package/node_modules/pi-lens/dist/chunk-34OCDWOS.js +48 -0
  74. package/node_modules/pi-lens/dist/chunk-3FERWMCH.js +144 -0
  75. package/node_modules/pi-lens/dist/chunk-3JL6IFD7.js +97 -0
  76. package/node_modules/pi-lens/dist/chunk-3JSEWUWI.js +327 -0
  77. package/node_modules/pi-lens/dist/chunk-3MED75HT.js +37 -0
  78. package/node_modules/pi-lens/dist/chunk-3MRXIJ6I.js +79 -0
  79. package/node_modules/pi-lens/dist/chunk-3P4PF2BX.js +2250 -0
  80. package/node_modules/pi-lens/dist/chunk-3PNFWVHT.js +201 -0
  81. package/node_modules/pi-lens/dist/chunk-3TTPKMEF.js +162 -0
  82. package/node_modules/pi-lens/dist/chunk-5JHXUETW.js +326 -0
  83. package/node_modules/pi-lens/dist/chunk-5W3R6LFT.js +24 -0
  84. package/node_modules/pi-lens/dist/chunk-64LU2OVH.js +341 -0
  85. package/node_modules/pi-lens/dist/chunk-6B5I6ICN.js +44 -0
  86. package/node_modules/pi-lens/dist/chunk-6P54TMWL.js +274 -0
  87. package/node_modules/pi-lens/dist/chunk-6UYA642J.js +145 -0
  88. package/node_modules/pi-lens/dist/chunk-6XX5HCLK.js +398 -0
  89. package/node_modules/pi-lens/dist/chunk-7AXO3ZDF.js +30 -0
  90. package/node_modules/pi-lens/dist/chunk-7BX5DWSA.js +1907 -0
  91. package/node_modules/pi-lens/dist/chunk-7ELY2CSM.js +902 -0
  92. package/node_modules/pi-lens/dist/chunk-7M4T5N3V.js +38 -0
  93. package/node_modules/pi-lens/dist/chunk-7U2IDNXN.js +37 -0
  94. package/node_modules/pi-lens/dist/chunk-ABBOA7UD.js +157 -0
  95. package/node_modules/pi-lens/dist/chunk-AFZYMAIV.js +756 -0
  96. package/node_modules/pi-lens/dist/chunk-ALQRYH6O.js +112 -0
  97. package/node_modules/pi-lens/dist/chunk-AXKPQ6ZI.js +1610 -0
  98. package/node_modules/pi-lens/dist/chunk-BHWHXMQ2.js +62 -0
  99. package/node_modules/pi-lens/dist/chunk-BJF25SUG.js +22 -0
  100. package/node_modules/pi-lens/dist/chunk-BNKLYOOO.js +18 -0
  101. package/node_modules/pi-lens/dist/chunk-BW5KFIQC.js +59 -0
  102. package/node_modules/pi-lens/dist/chunk-CBD2B5CP.js +599 -0
  103. package/node_modules/pi-lens/dist/chunk-CFYISHUW.js +42 -0
  104. package/node_modules/pi-lens/dist/chunk-CMU4RMJB.js +30 -0
  105. package/node_modules/pi-lens/dist/chunk-CULQYFLU.js +14 -0
  106. package/node_modules/pi-lens/dist/chunk-D65GOCJB.js +289 -0
  107. package/node_modules/pi-lens/dist/chunk-D6YF5HKX.js +59 -0
  108. package/node_modules/pi-lens/dist/chunk-DMS52BEP.js +342 -0
  109. package/node_modules/pi-lens/dist/chunk-ELVWJYRV.js +211 -0
  110. package/node_modules/pi-lens/dist/chunk-EUT3B22Y.js +27 -0
  111. package/node_modules/pi-lens/dist/chunk-F5VLZHUW.js +146 -0
  112. package/node_modules/pi-lens/dist/chunk-FC4RP4I2.js +12 -0
  113. package/node_modules/pi-lens/dist/chunk-FGALODG3.js +55 -0
  114. package/node_modules/pi-lens/dist/chunk-G3RLJYA2.js +2358 -0
  115. package/node_modules/pi-lens/dist/chunk-GAYGGICG.js +32 -0
  116. package/node_modules/pi-lens/dist/chunk-H2W2AXD3.js +419 -0
  117. package/node_modules/pi-lens/dist/chunk-H5EV3VMF.js +114 -0
  118. package/node_modules/pi-lens/dist/chunk-HREZQCT3.js +106 -0
  119. package/node_modules/pi-lens/dist/chunk-HSIRMK2D.js +517 -0
  120. package/node_modules/pi-lens/dist/chunk-IMSQR4WO.js +184 -0
  121. package/node_modules/pi-lens/dist/chunk-IQZXOZ7S.js +4816 -0
  122. package/node_modules/pi-lens/dist/chunk-IR6XFA5P.js +37 -0
  123. package/node_modules/pi-lens/dist/chunk-IUKPRZER.js +78 -0
  124. package/node_modules/pi-lens/dist/chunk-IUR76K6A.js +262 -0
  125. package/node_modules/pi-lens/dist/chunk-J3FZR3YY.js +98 -0
  126. package/node_modules/pi-lens/dist/chunk-J6DFZDFA.js +562 -0
  127. package/node_modules/pi-lens/dist/chunk-J7WJZ6W7.js +50 -0
  128. package/node_modules/pi-lens/dist/chunk-JONGANYH.js +202 -0
  129. package/node_modules/pi-lens/dist/chunk-KJCWXUUS.js +425 -0
  130. package/node_modules/pi-lens/dist/chunk-KJN4IOEJ.js +17 -0
  131. package/node_modules/pi-lens/dist/chunk-KMGPUKFD.js +25 -0
  132. package/node_modules/pi-lens/dist/chunk-LD7WFTRX.js +4533 -0
  133. package/node_modules/pi-lens/dist/chunk-LJDODBBZ.js +78 -0
  134. package/node_modules/pi-lens/dist/chunk-LNOMA3MP.js +169 -0
  135. package/node_modules/pi-lens/dist/chunk-MGIWSROG.js +2334 -0
  136. package/node_modules/pi-lens/dist/chunk-MQA2YBAH.js +308 -0
  137. package/node_modules/pi-lens/dist/chunk-MTDRLSI7.js +21720 -0
  138. package/node_modules/pi-lens/dist/chunk-N2IRDBZI.js +2355 -0
  139. package/node_modules/pi-lens/dist/chunk-N77WFUL7.js +50 -0
  140. package/node_modules/pi-lens/dist/chunk-N7YNJE5R.js +466 -0
  141. package/node_modules/pi-lens/dist/chunk-NABLC7W3.js +148 -0
  142. package/node_modules/pi-lens/dist/chunk-NFXP47RV.js +999 -0
  143. package/node_modules/pi-lens/dist/chunk-NJF2X5XF.js +45 -0
  144. package/node_modules/pi-lens/dist/chunk-NXL4FFQQ.js +47 -0
  145. package/node_modules/pi-lens/dist/chunk-O7HZX7CA.js +309 -0
  146. package/node_modules/pi-lens/dist/chunk-OC7LYAU5.js +708 -0
  147. package/node_modules/pi-lens/dist/chunk-OEX24ECI.js +348 -0
  148. package/node_modules/pi-lens/dist/chunk-OYOB3ZFG.js +78 -0
  149. package/node_modules/pi-lens/dist/chunk-OYTMZXRF.js +41 -0
  150. package/node_modules/pi-lens/dist/chunk-OZJINN4O.js +84 -0
  151. package/node_modules/pi-lens/dist/chunk-PCHDGUKT.js +23 -0
  152. package/node_modules/pi-lens/dist/chunk-QOZXJ4NA.js +3364 -0
  153. package/node_modules/pi-lens/dist/chunk-QYF5S6P6.js +45 -0
  154. package/node_modules/pi-lens/dist/chunk-RJFED73B.js +79 -0
  155. package/node_modules/pi-lens/dist/chunk-RTQNRM5X.js +27 -0
  156. package/node_modules/pi-lens/dist/chunk-S6AMWKPC.js +189 -0
  157. package/node_modules/pi-lens/dist/chunk-T4QZ6FEH.js +308 -0
  158. package/node_modules/pi-lens/dist/chunk-T54VJRAD.js +5456 -0
  159. package/node_modules/pi-lens/dist/chunk-TA5L5KWQ.js +167 -0
  160. package/node_modules/pi-lens/dist/chunk-TQFBZVCG.js +27 -0
  161. package/node_modules/pi-lens/dist/chunk-U52SAGRM.js +62 -0
  162. package/node_modules/pi-lens/dist/chunk-UEAHAMEI.js +5814 -0
  163. package/node_modules/pi-lens/dist/chunk-UGSMCQ4D.js +327 -0
  164. package/node_modules/pi-lens/dist/chunk-UOPVJQ4N.js +103 -0
  165. package/node_modules/pi-lens/dist/chunk-USHG4DLH.js +459 -0
  166. package/node_modules/pi-lens/dist/chunk-UXVNL3D7.js +23 -0
  167. package/node_modules/pi-lens/dist/chunk-V5MEBST3.js +4139 -0
  168. package/node_modules/pi-lens/dist/chunk-VGEVL5EQ.js +29 -0
  169. package/node_modules/pi-lens/dist/chunk-VPWKF3GN.js +87 -0
  170. package/node_modules/pi-lens/dist/chunk-VSMJK3ZJ.js +1250 -0
  171. package/node_modules/pi-lens/dist/chunk-VYKKMYVT.js +560 -0
  172. package/node_modules/pi-lens/dist/chunk-VZHJS6DR.js +442 -0
  173. package/node_modules/pi-lens/dist/chunk-WATC3IQR.js +213 -0
  174. package/node_modules/pi-lens/dist/chunk-WPE5FPGR.js +54 -0
  175. package/node_modules/pi-lens/dist/chunk-WSEWKCXU.js +188 -0
  176. package/node_modules/pi-lens/dist/chunk-WW5BLB74.js +659 -0
  177. package/node_modules/pi-lens/dist/chunk-XGUL4SLQ.js +406 -0
  178. package/node_modules/pi-lens/dist/chunk-XHSCVSOL.js +170 -0
  179. package/node_modules/pi-lens/dist/chunk-XIMYZ3JA.js +27 -0
  180. package/node_modules/pi-lens/dist/chunk-YLN4K6WD.js +385 -0
  181. package/node_modules/pi-lens/dist/chunk-Z3CCVDUB.js +76 -0
  182. package/node_modules/pi-lens/dist/chunk-Z54ZSOBZ.js +61 -0
  183. package/node_modules/pi-lens/dist/chunk-Z6BB4JLQ.js +478 -0
  184. package/node_modules/pi-lens/dist/chunk-Z7QQA2KT.js +27 -0
  185. package/node_modules/pi-lens/dist/chunk-ZETYB3XG.js +2626 -0
  186. package/node_modules/pi-lens/dist/chunk-ZMOMPX2Z.js +87 -0
  187. package/node_modules/pi-lens/dist/chunk-ZOEYVXSV.js +149 -0
  188. package/node_modules/pi-lens/dist/chunk-ZZUFZUQZ.js +12120 -0
  189. package/node_modules/pi-lens/dist/index.js +39712 -29876
  190. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +186 -232
  191. package/node_modules/pi-lens/dist/mcp/cli.js +137 -98
  192. package/node_modules/pi-lens/dist/mcp/server.js +22688 -1573
  193. package/node_modules/pi-lens/dist/mcp/worker.js +97 -38
  194. package/node_modules/pi-lens/dist/probes/installer.js +135 -0
  195. package/node_modules/pi-lens/dist/workers/project-snapshot-persist-worker.js +22 -0
  196. package/node_modules/pi-lens/dist/workers/review-graph-persist-worker.js +15 -0
  197. package/node_modules/pi-lens/docs/agent-guide.md +13 -4
  198. package/node_modules/pi-lens/docs/agent-tools.md +42 -0
  199. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +5 -4
  200. package/node_modules/pi-lens/docs/configuration.md +28 -2
  201. package/node_modules/pi-lens/docs/custom-rules.md +25 -2
  202. package/node_modules/pi-lens/docs/environment-variables.md +86 -8
  203. package/node_modules/pi-lens/docs/features.md +45 -5
  204. package/node_modules/pi-lens/docs/globalconfig.md +2 -1
  205. package/node_modules/pi-lens/docs/io-bridge-v2-migration.md +94 -0
  206. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +37 -4
  207. package/node_modules/pi-lens/docs/lsp-idle-eviction.md +124 -0
  208. package/node_modules/pi-lens/docs/mcp.md +21 -5
  209. package/node_modules/pi-lens/docs/merge-queue-rollout.md +77 -0
  210. package/node_modules/pi-lens/docs/pi-lens-fixer.md +160 -88
  211. package/node_modules/pi-lens/docs/pi-lens-investigator.md +74 -26
  212. package/node_modules/pi-lens/docs/pi-lens-merge-policy.md +736 -0
  213. package/node_modules/pi-lens/docs/pi-lens-monitor.md +75 -7
  214. package/node_modules/pi-lens/docs/pi-lens-retro.md +6 -4
  215. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +189 -48
  216. package/node_modules/pi-lens/docs/pi-lens-subagent.md +246 -45
  217. package/node_modules/pi-lens/docs/pi-lens-warden.md +18 -7
  218. package/node_modules/pi-lens/docs/public-api-stability.md +55 -0
  219. package/node_modules/pi-lens/docs/release-qa-baseline.md +84 -17
  220. package/node_modules/pi-lens/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
  221. package/node_modules/pi-lens/docs/schema/pi-lens-config-v1.json +530 -0
  222. package/node_modules/pi-lens/docs/servercapabilities.md +56 -49
  223. package/node_modules/pi-lens/docs/settings.md +1 -0
  224. package/node_modules/pi-lens/docs/usage.md +5 -1
  225. package/node_modules/pi-lens/docs/word-index.md +6 -0
  226. package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm +0 -0
  227. package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm.json +3 -3
  228. package/node_modules/pi-lens/package.json +18 -6
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
  237. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +1275 -62
  238. package/node_modules/pi-lens/scripts/download-grammars.js +5 -0
  239. package/node_modules/pi-lens/scripts/grammars.lock.json +6 -1
  240. package/node_modules/pi-lens/scripts/install-selftest.mjs +33 -34
  241. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +13 -4
  242. package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +18 -0
  243. package/node_modules/pi-web-access/CHANGELOG.md +28 -0
  244. package/node_modules/pi-web-access/README.md +10 -6
  245. package/node_modules/pi-web-access/ceramic.ts +219 -0
  246. package/node_modules/pi-web-access/curator-page.ts +3 -1
  247. package/node_modules/pi-web-access/curator-server.ts +1 -0
  248. package/node_modules/pi-web-access/dist/index.js +846 -588
  249. package/node_modules/pi-web-access/dist/mcp-cli.js +725 -516
  250. package/node_modules/pi-web-access/gemini-search.ts +8 -4
  251. package/node_modules/pi-web-access/github-extract.ts +34 -2
  252. package/node_modules/pi-web-access/index.ts +72 -30
  253. package/node_modules/pi-web-access/openai-search.ts +3 -3
  254. package/node_modules/pi-web-access/package.json +2 -2
  255. package/node_modules/pi-web-access/page-query.ts +6 -9
  256. package/node_modules/pi-web-access/parallel-mcp.ts +2 -0
  257. package/node_modules/pi-web-access/query-rewrite.ts +2 -2
  258. package/node_modules/pi-web-access/storage.ts +49 -0
  259. package/node_modules/pi-web-access/summary-review.ts +7 -6
  260. package/node_modules/pi-web-access/utils.ts +21 -6
  261. package/node_modules/pi-web-access/web-tool-core.ts +1 -0
  262. package/package.json +19 -19
  263. package/node_modules/@dietrichgebert/ponytail/README.es.md +0 -212
  264. package/node_modules/@dietrichgebert/ponytail/README.ja.md +0 -212
  265. package/node_modules/@dietrichgebert/ponytail/README.ko.md +0 -212
  266. package/node_modules/@dietrichgebert/ponytail/README.zh-CN.md +0 -212
  267. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -35
  268. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +0 -1610
  269. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +0 -593
  270. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +0 -147
  271. package/node_modules/pi-lens/dist/clients/agent-nudge.js +0 -325
  272. package/node_modules/pi-lens/dist/clients/analysed-root.js +0 -1
  273. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +0 -731
  274. package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +0 -146
  275. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +0 -118
  276. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -10
  277. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +0 -154
  278. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +0 -75
  279. package/node_modules/pi-lens/dist/clients/atomic-write.js +0 -189
  280. package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +0 -12
  281. package/node_modules/pi-lens/dist/clients/bash-file-access.js +0 -1056
  282. package/node_modules/pi-lens/dist/clients/biome-client.js +0 -357
  283. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -837
  284. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +0 -129
  285. package/node_modules/pi-lens/dist/clients/bootstrap.js +0 -569
  286. package/node_modules/pi-lens/dist/clients/bounded-cache.js +0 -190
  287. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +0 -202
  288. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +0 -295
  289. package/node_modules/pi-lens/dist/clients/build-identity.js +0 -95
  290. package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +0 -113
  291. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +0 -105
  292. package/node_modules/pi-lens/dist/clients/bus-publish.js +0 -171
  293. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +0 -190
  294. package/node_modules/pi-lens/dist/clients/cache-manager.js +0 -524
  295. package/node_modules/pi-lens/dist/clients/cache-observability.js +0 -1313
  296. package/node_modules/pi-lens/dist/clients/call-graph.js +0 -852
  297. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +0 -422
  298. package/node_modules/pi-lens/dist/clients/cascade-budget.js +0 -196
  299. package/node_modules/pi-lens/dist/clients/cascade-format.js +0 -315
  300. package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -31
  301. package/node_modules/pi-lens/dist/clients/cascade-types.js +0 -9
  302. package/node_modules/pi-lens/dist/clients/child-unref.js +0 -124
  303. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +0 -286
  304. package/node_modules/pi-lens/dist/clients/codebase-model.js +0 -173
  305. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +0 -40
  306. package/node_modules/pi-lens/dist/clients/complexity-client.js +0 -462
  307. package/node_modules/pi-lens/dist/clients/config-core/deny.js +0 -221
  308. package/node_modules/pi-lens/dist/clients/config-core/index.js +0 -50
  309. package/node_modules/pi-lens/dist/clients/config-core/merge.js +0 -357
  310. package/node_modules/pi-lens/dist/clients/config-core/normalize.js +0 -340
  311. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +0 -248
  312. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +0 -164
  313. package/node_modules/pi-lens/dist/clients/config-core/records.js +0 -218
  314. package/node_modules/pi-lens/dist/clients/config-core/resolve.js +0 -125
  315. package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +0 -78
  316. package/node_modules/pi-lens/dist/clients/config-core/schema.js +0 -165
  317. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +0 -285
  318. package/node_modules/pi-lens/dist/clients/config-locations.js +0 -388
  319. package/node_modules/pi-lens/dist/clients/config-resolve.js +0 -798
  320. package/node_modules/pi-lens/dist/clients/config-schema.js +0 -251
  321. package/node_modules/pi-lens/dist/clients/config-warn.js +0 -407
  322. package/node_modules/pi-lens/dist/clients/console-guard-install.js +0 -26
  323. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +0 -42
  324. package/node_modules/pi-lens/dist/clients/dead-code-client.js +0 -510
  325. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -30
  326. package/node_modules/pi-lens/dist/clients/deadline-utils.js +0 -280
  327. package/node_modules/pi-lens/dist/clients/debug-handles.js +0 -211
  328. package/node_modules/pi-lens/dist/clients/debug-heap.js +0 -174
  329. package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +0 -106
  330. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +0 -426
  331. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +0 -169
  332. package/node_modules/pi-lens/dist/clients/dependency-checker.js +0 -885
  333. package/node_modules/pi-lens/dist/clients/deps/ast-grep-napi.js +0 -22
  334. package/node_modules/pi-lens/dist/clients/deps/js-yaml.js +0 -9
  335. package/node_modules/pi-lens/dist/clients/deps/minimatch.js +0 -4
  336. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +0 -14
  337. package/node_modules/pi-lens/dist/clients/deps/typebox.js +0 -14
  338. package/node_modules/pi-lens/dist/clients/deps/vscode-jsonrpc.js +0 -1
  339. package/node_modules/pi-lens/dist/clients/deps/web-tree-sitter.js +0 -24
  340. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +0 -630
  341. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +0 -305
  342. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +0 -73
  343. package/node_modules/pi-lens/dist/clients/diagnostic-tracker.js +0 -105
  344. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +0 -230
  345. package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -65
  346. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -343
  347. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -35
  348. package/node_modules/pi-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
  349. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +0 -1269
  350. package/node_modules/pi-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
  351. package/node_modules/pi-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
  352. package/node_modules/pi-lens/dist/clients/dispatch/fact-runner.js +0 -30
  353. package/node_modules/pi-lens/dist/clients/dispatch/fact-scheduler.js +0 -68
  354. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +0 -377
  355. package/node_modules/pi-lens/dist/clients/dispatch/facts/comment-facts.js +0 -22
  356. package/node_modules/pi-lens/dist/clients/dispatch/facts/file-content.js +0 -19
  357. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +0 -348
  358. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +0 -204
  359. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
  360. package/node_modules/pi-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
  361. package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +0 -339
  362. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +0 -417
  363. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +0 -89
  364. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +0 -2377
  365. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -11
  366. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +0 -87
  367. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -278
  368. package/node_modules/pi-lens/dist/clients/dispatch/priorities.js +0 -20
  369. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +0 -50
  370. package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +0 -69
  371. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +0 -135
  372. package/node_modules/pi-lens/dist/clients/dispatch/rules/async-noise.js +0 -40
  373. package/node_modules/pi-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
  374. package/node_modules/pi-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
  375. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -32
  376. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -31
  377. package/node_modules/pi-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
  378. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +0 -72
  379. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -74
  380. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
  381. package/node_modules/pi-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
  382. package/node_modules/pi-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
  383. package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
  384. package/node_modules/pi-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
  385. package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
  386. package/node_modules/pi-lens/dist/clients/dispatch/runner-context.js +0 -52
  387. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -111
  388. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
  389. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -296
  390. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -219
  391. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -82
  392. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -416
  393. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -183
  394. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -176
  395. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -164
  396. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -195
  397. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -137
  398. package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -29
  399. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -69
  400. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -167
  401. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +0 -104
  402. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -135
  403. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -91
  404. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -171
  405. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -940
  406. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -117
  407. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +0 -108
  408. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -99
  409. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -110
  410. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -379
  411. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -167
  412. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -102
  413. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +0 -414
  414. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -85
  415. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -120
  416. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -62
  417. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
  418. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +0 -169
  419. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -99
  420. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -88
  421. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -256
  422. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -173
  423. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -102
  424. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -128
  425. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -259
  426. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -183
  427. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -166
  428. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -163
  429. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -174
  430. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -168
  431. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -125
  432. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -643
  433. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -253
  434. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
  435. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
  436. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
  437. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
  438. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
  439. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
  440. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
  441. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
  442. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -15
  443. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -128
  444. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
  445. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -95
  446. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -79
  447. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +0 -79
  448. package/node_modules/pi-lens/dist/clients/dispatch/tool-profile.js +0 -30
  449. package/node_modules/pi-lens/dist/clients/dispatch/types.js +0 -21
  450. package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
  451. package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
  452. package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -32
  453. package/node_modules/pi-lens/dist/clients/disposition-publish.js +0 -124
  454. package/node_modules/pi-lens/dist/clients/durable-store.js +0 -97
  455. package/node_modules/pi-lens/dist/clients/effective-config.js +0 -415
  456. package/node_modules/pi-lens/dist/clients/env-utils.js +0 -83
  457. package/node_modules/pi-lens/dist/clients/error-class.js +0 -23
  458. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +0 -17
  459. package/node_modules/pi-lens/dist/clients/event-loop-hold.js +0 -274
  460. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +0 -250
  461. package/node_modules/pi-lens/dist/clients/extension-log.js +0 -504
  462. package/node_modules/pi-lens/dist/clients/extension-mode.js +0 -73
  463. package/node_modules/pi-lens/dist/clients/feature-hints.js +0 -103
  464. package/node_modules/pi-lens/dist/clients/file-kinds.js +0 -412
  465. package/node_modules/pi-lens/dist/clients/file-role.js +0 -134
  466. package/node_modules/pi-lens/dist/clients/file-time.js +0 -160
  467. package/node_modules/pi-lens/dist/clients/file-utils.js +0 -1032
  468. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +0 -494
  469. package/node_modules/pi-lens/dist/clients/finding-identity.js +0 -88
  470. package/node_modules/pi-lens/dist/clients/fix-worklog.js +0 -103
  471. package/node_modules/pi-lens/dist/clients/format-events-publish.js +0 -343
  472. package/node_modules/pi-lens/dist/clients/format-service.js +0 -222
  473. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +0 -9
  474. package/node_modules/pi-lens/dist/clients/formatters.js +0 -2032
  475. package/node_modules/pi-lens/dist/clients/freshness-cadence.js +0 -17
  476. package/node_modules/pi-lens/dist/clients/freshness.js +0 -38
  477. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +0 -394
  478. package/node_modules/pi-lens/dist/clients/generation-guard.js +0 -215
  479. package/node_modules/pi-lens/dist/clients/git-guard.js +0 -1136
  480. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +0 -243
  481. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +0 -509
  482. package/node_modules/pi-lens/dist/clients/go-client.js +0 -104
  483. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +0 -605
  484. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +0 -348
  485. package/node_modules/pi-lens/dist/clients/grammar-source.js +0 -465
  486. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +0 -135
  487. package/node_modules/pi-lens/dist/clients/hashline-anchor.js +0 -424
  488. package/node_modules/pi-lens/dist/clients/hook-budgets.js +0 -76
  489. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +0 -140
  490. package/node_modules/pi-lens/dist/clients/host-ports.js +0 -39
  491. package/node_modules/pi-lens/dist/clients/indent-retarget.js +0 -154
  492. package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +0 -186
  493. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +0 -156
  494. package/node_modules/pi-lens/dist/clients/installer/index.js +0 -5416
  495. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -58
  496. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +0 -783
  497. package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +0 -7
  498. package/node_modules/pi-lens/dist/clients/instance-reaper.js +0 -1137
  499. package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +0 -145
  500. package/node_modules/pi-lens/dist/clients/instance-registry.js +0 -773
  501. package/node_modules/pi-lens/dist/clients/jscpd-client.js +0 -378
  502. package/node_modules/pi-lens/dist/clients/json-cache-read.js +0 -65
  503. package/node_modules/pi-lens/dist/clients/knip-client.js +0 -788
  504. package/node_modules/pi-lens/dist/clients/language-policy.js +0 -252
  505. package/node_modules/pi-lens/dist/clients/language-profile.js +0 -361
  506. package/node_modules/pi-lens/dist/clients/language-registry.js +0 -603
  507. package/node_modules/pi-lens/dist/clients/latency-logger.js +0 -727
  508. package/node_modules/pi-lens/dist/clients/lazy-import.js +0 -21
  509. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +0 -54
  510. package/node_modules/pi-lens/dist/clients/lens-config.js +0 -404
  511. package/node_modules/pi-lens/dist/clients/lens-engine.js +0 -358
  512. package/node_modules/pi-lens/dist/clients/lens-events.js +0 -125
  513. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +0 -467
  514. package/node_modules/pi-lens/dist/clients/lens-map.js +0 -1156
  515. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +0 -74
  516. package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -222
  517. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +0 -178
  518. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +0 -421
  519. package/node_modules/pi-lens/dist/clients/lsp/client.js +0 -4593
  520. package/node_modules/pi-lens/dist/clients/lsp/config.js +0 -691
  521. package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +0 -41
  522. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +0 -225
  523. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +0 -467
  524. package/node_modules/pi-lens/dist/clients/lsp/edits.js +0 -1219
  525. package/node_modules/pi-lens/dist/clients/lsp/index.js +0 -8305
  526. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +0 -216
  527. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +0 -298
  528. package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -63
  529. package/node_modules/pi-lens/dist/clients/lsp/launch.js +0 -746
  530. package/node_modules/pi-lens/dist/clients/lsp/lombok.js +0 -158
  531. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +0 -5
  532. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -251
  533. package/node_modules/pi-lens/dist/clients/lsp/position-encoding.js +0 -61
  534. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -83
  535. package/node_modules/pi-lens/dist/clients/lsp/server.js +0 -3290
  536. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +0 -192
  537. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +0 -17
  538. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -56
  539. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +0 -332
  540. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
  541. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +0 -85
  542. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/index.js +0 -10
  543. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +0 -392
  544. package/node_modules/pi-lens/dist/clients/lsp/watch-queue.js +0 -61
  545. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
  546. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
  547. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -184
  548. package/node_modules/pi-lens/dist/clients/lsp-budget.js +0 -186
  549. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +0 -110
  550. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +0 -9
  551. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +0 -396
  552. package/node_modules/pi-lens/dist/clients/lsp-status.js +0 -59
  553. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +0 -40
  554. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +0 -420
  555. package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +0 -31
  556. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +0 -523
  557. package/node_modules/pi-lens/dist/clients/mcp/review.js +0 -197
  558. package/node_modules/pi-lens/dist/clients/mcp/session.js +0 -412
  559. package/node_modules/pi-lens/dist/clients/memory-sampler.js +0 -208
  560. package/node_modules/pi-lens/dist/clients/message-end-attribution.js +0 -30
  561. package/node_modules/pi-lens/dist/clients/metrics-client.js +0 -107
  562. package/node_modules/pi-lens/dist/clients/metrics-history.js +0 -327
  563. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +0 -263
  564. package/node_modules/pi-lens/dist/clients/model-provider.js +0 -53
  565. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +0 -189
  566. package/node_modules/pi-lens/dist/clients/module-report.js +0 -2150
  567. package/node_modules/pi-lens/dist/clients/mutating-tool.js +0 -651
  568. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +0 -368
  569. package/node_modules/pi-lens/dist/clients/mutation-bridge.js +0 -240
  570. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -734
  571. package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +0 -101
  572. package/node_modules/pi-lens/dist/clients/observed-mutation.js +0 -1253
  573. package/node_modules/pi-lens/dist/clients/oldtext-autopatch.js +0 -128
  574. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +0 -496
  575. package/node_modules/pi-lens/dist/clients/opengrep-client.js +0 -333
  576. package/node_modules/pi-lens/dist/clients/opengrep-config.js +0 -76
  577. package/node_modules/pi-lens/dist/clients/package-manager.js +0 -607
  578. package/node_modules/pi-lens/dist/clients/package-root.js +0 -38
  579. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +0 -439
  580. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +0 -43
  581. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +0 -108
  582. package/node_modules/pi-lens/dist/clients/path-utils.js +0 -1244
  583. package/node_modules/pi-lens/dist/clients/performance-report.js +0 -331
  584. package/node_modules/pi-lens/dist/clients/persist-debounce.js +0 -70
  585. package/node_modules/pi-lens/dist/clients/persistent-reverify.js +0 -271
  586. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +0 -119
  587. package/node_modules/pi-lens/dist/clients/pipeline.js +0 -1480
  588. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +0 -37
  589. package/node_modules/pi-lens/dist/clients/print-mode.js +0 -21
  590. package/node_modules/pi-lens/dist/clients/probe-home-state.js +0 -228
  591. package/node_modules/pi-lens/dist/clients/process-bridge.js +0 -66
  592. package/node_modules/pi-lens/dist/clients/process-singletons.js +0 -210
  593. package/node_modules/pi-lens/dist/clients/process-snapshot.js +0 -68
  594. package/node_modules/pi-lens/dist/clients/project-changes.js +0 -181
  595. package/node_modules/pi-lens/dist/clients/project-conventions.js +0 -171
  596. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +0 -137
  597. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +0 -109
  598. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
  599. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
  600. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
  601. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
  602. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
  603. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
  604. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
  605. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
  606. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
  607. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
  608. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
  609. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +0 -520
  610. package/node_modules/pi-lens/dist/clients/project-diagnostics/types.js +0 -1
  611. package/node_modules/pi-lens/dist/clients/project-lens-config.js +0 -807
  612. package/node_modules/pi-lens/dist/clients/project-report.js +0 -701
  613. package/node_modules/pi-lens/dist/clients/project-scale.js +0 -237
  614. package/node_modules/pi-lens/dist/clients/project-scan-policy.js +0 -11
  615. package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +0 -48
  616. package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +0 -20
  617. package/node_modules/pi-lens/dist/clients/project-snapshot.js +0 -1653
  618. package/node_modules/pi-lens/dist/clients/project-trust.js +0 -181
  619. package/node_modules/pi-lens/dist/clients/python-environment.js +0 -217
  620. package/node_modules/pi-lens/dist/clients/python-provenance.js +0 -639
  621. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +0 -47
  622. package/node_modules/pi-lens/dist/clients/quiet-window.js +0 -236
  623. package/node_modules/pi-lens/dist/clients/read-bridge.js +0 -139
  624. package/node_modules/pi-lens/dist/clients/read-expansion.js +0 -266
  625. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +0 -251
  626. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +0 -1306
  627. package/node_modules/pi-lens/dist/clients/read-guard.js +0 -1561
  628. package/node_modules/pi-lens/dist/clients/recent-touches.js +0 -240
  629. package/node_modules/pi-lens/dist/clients/redact/secrets.js +0 -449
  630. package/node_modules/pi-lens/dist/clients/resource-sampler.js +0 -628
  631. package/node_modules/pi-lens/dist/clients/reverse-deps.js +0 -270
  632. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +0 -5126
  633. package/node_modules/pi-lens/dist/clients/review-graph/format.js +0 -33
  634. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +0 -163
  635. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +0 -481
  636. package/node_modules/pi-lens/dist/clients/review-graph/persist-worker.js +0 -10
  637. package/node_modules/pi-lens/dist/clients/review-graph/query.js +0 -244
  638. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +0 -21
  639. package/node_modules/pi-lens/dist/clients/review-graph/service.js +0 -96
  640. package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -82
  641. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +0 -103
  642. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +0 -299
  643. package/node_modules/pi-lens/dist/clients/review-graph/types.js +0 -1
  644. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +0 -449
  645. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +0 -81
  646. package/node_modules/pi-lens/dist/clients/ruff-client.js +0 -179
  647. package/node_modules/pi-lens/dist/clients/rules-scanner.js +0 -131
  648. package/node_modules/pi-lens/dist/clients/run-duration.js +0 -55
  649. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +0 -746
  650. package/node_modules/pi-lens/dist/clients/runtime-config.js +0 -77
  651. package/node_modules/pi-lens/dist/clients/runtime-context.js +0 -211
  652. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +0 -1324
  653. package/node_modules/pi-lens/dist/clients/runtime-session.js +0 -2485
  654. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +0 -1295
  655. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +0 -2049
  656. package/node_modules/pi-lens/dist/clients/runtime-turn.js +0 -3767
  657. package/node_modules/pi-lens/dist/clients/rust-client.js +0 -97
  658. package/node_modules/pi-lens/dist/clients/safe-spawn.js +0 -2357
  659. package/node_modules/pi-lens/dist/clients/sanitize.js +0 -286
  660. package/node_modules/pi-lens/dist/clients/scan-utils.js +0 -25
  661. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +0 -165
  662. package/node_modules/pi-lens/dist/clients/search-read-registration.js +0 -94
  663. package/node_modules/pi-lens/dist/clients/secret-findings.js +0 -114
  664. package/node_modules/pi-lens/dist/clients/security-scan-client.js +0 -352
  665. package/node_modules/pi-lens/dist/clients/session-event-guard.js +0 -297
  666. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +0 -484
  667. package/node_modules/pi-lens/dist/clients/session-start-observability.js +0 -94
  668. package/node_modules/pi-lens/dist/clients/session-state-store.js +0 -101
  669. package/node_modules/pi-lens/dist/clients/session-summary.js +0 -15
  670. package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +0 -27
  671. package/node_modules/pi-lens/dist/clients/sg-runner.js +0 -876
  672. package/node_modules/pi-lens/dist/clients/sgconfig.js +0 -347
  673. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +0 -338
  674. package/node_modules/pi-lens/dist/clients/single-flight.js +0 -158
  675. package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +0 -108
  676. package/node_modules/pi-lens/dist/clients/skills-resolver.js +0 -141
  677. package/node_modules/pi-lens/dist/clients/slow-fs.js +0 -138
  678. package/node_modules/pi-lens/dist/clients/smells-rollup.js +0 -231
  679. package/node_modules/pi-lens/dist/clients/source-filter.js +0 -596
  680. package/node_modules/pi-lens/dist/clients/source-walker.js +0 -211
  681. package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +0 -120
  682. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +0 -110
  683. package/node_modules/pi-lens/dist/clients/stale-marker.js +0 -17
  684. package/node_modules/pi-lens/dist/clients/startup-scan.js +0 -400
  685. package/node_modules/pi-lens/dist/clients/startup-timing.js +0 -130
  686. package/node_modules/pi-lens/dist/clients/string-utils.js +0 -33
  687. package/node_modules/pi-lens/dist/clients/subagent-mode.js +0 -111
  688. package/node_modules/pi-lens/dist/clients/symbol-containment.js +0 -24
  689. package/node_modules/pi-lens/dist/clients/symbol-types.js +0 -5
  690. package/node_modules/pi-lens/dist/clients/test-runner-client.js +0 -2507
  691. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +0 -287
  692. package/node_modules/pi-lens/dist/clients/todo-scanner.js +0 -229
  693. package/node_modules/pi-lens/dist/clients/tool-agreement.js +0 -423
  694. package/node_modules/pi-lens/dist/clients/tool-config.js +0 -249
  695. package/node_modules/pi-lens/dist/clients/tool-cwd.js +0 -270
  696. package/node_modules/pi-lens/dist/clients/tool-definition.js +0 -47
  697. package/node_modules/pi-lens/dist/clients/tool-event.js +0 -105
  698. package/node_modules/pi-lens/dist/clients/tool-policy.js +0 -2755
  699. package/node_modules/pi-lens/dist/clients/tool-probe.js +0 -53
  700. package/node_modules/pi-lens/dist/clients/tool-render.js +0 -156
  701. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +0 -118
  702. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +0 -364
  703. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +0 -4195
  704. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +0 -100
  705. package/node_modules/pi-lens/dist/clients/tree-sitter-navigator.js +0 -269
  706. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +0 -569
  707. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +0 -158
  708. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
  709. package/node_modules/pi-lens/dist/clients/trivy-client.js +0 -467
  710. package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -50
  711. package/node_modules/pi-lens/dist/clients/turn-context.js +0 -52
  712. package/node_modules/pi-lens/dist/clients/turn-end/lane.js +0 -51
  713. package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -112
  714. package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +0 -204
  715. package/node_modules/pi-lens/dist/clients/turn-summary-render.js +0 -72
  716. package/node_modules/pi-lens/dist/clients/turn-summary.js +0 -132
  717. package/node_modules/pi-lens/dist/clients/typos-config.js +0 -29
  718. package/node_modules/pi-lens/dist/clients/user-notify.js +0 -51
  719. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +0 -57
  720. package/node_modules/pi-lens/dist/clients/warm-attach.js +0 -305
  721. package/node_modules/pi-lens/dist/clients/widget-state.js +0 -1808
  722. package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -49
  723. package/node_modules/pi-lens/dist/clients/word-index-store.js +0 -459
  724. package/node_modules/pi-lens/dist/clients/word-index.js +0 -2080
  725. package/node_modules/pi-lens/dist/clients/workspace-topology.js +0 -443
  726. package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +0 -65
  727. package/node_modules/pi-lens/dist/clients/zizmor-config.js +0 -340
  728. package/node_modules/pi-lens/dist/i18n.js +0 -69
  729. package/node_modules/pi-lens/dist/mcp/build-staleness.js +0 -124
  730. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +0 -583
  731. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +0 -129
  732. package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
  733. package/node_modules/pi-lens/dist/tools/activate-tools.js +0 -87
  734. package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +0 -137
  735. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +0 -244
  736. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +0 -762
  737. package/node_modules/pi-lens/dist/tools/effective-config.js +0 -90
  738. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +0 -375
  739. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +0 -2571
  740. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +0 -1745
  741. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +0 -1367
  742. package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +0 -294
  743. package/node_modules/pi-lens/dist/tools/module-report.js +0 -382
  744. package/node_modules/pi-lens/dist/tools/project-report.js +0 -86
  745. package/node_modules/pi-lens/dist/tools/render-compact.js +0 -374
  746. package/node_modules/pi-lens/dist/tools/scan-progress.js +0 -53
  747. package/node_modules/pi-lens/dist/tools/shared.js +0 -29
  748. package/node_modules/pi-lens/dist/tools/symbol-search.js +0 -155
  749. package/node_modules/pi-web-access/opencode-session-headers.ts +0 -24
  750. package/node_modules/remote-pi/README.md +0 -675
  751. package/node_modules/remote-pi/dist/actions/handlers.d.ts +0 -122
  752. package/node_modules/remote-pi/dist/actions/handlers.js +0 -160
  753. package/node_modules/remote-pi/dist/actions/handlers.js.map +0 -1
  754. package/node_modules/remote-pi/dist/actions/registry.d.ts +0 -39
  755. package/node_modules/remote-pi/dist/actions/registry.js +0 -58
  756. package/node_modules/remote-pi/dist/actions/registry.js.map +0 -1
  757. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +0 -2
  758. package/node_modules/remote-pi/dist/bin/supervisord.js +0 -86
  759. package/node_modules/remote-pi/dist/bin/supervisord.js.map +0 -1
  760. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +0 -58
  761. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +0 -71
  762. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +0 -1
  763. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +0 -60
  764. package/node_modules/remote-pi/dist/commands/list_commands.js +0 -73
  765. package/node_modules/remote-pi/dist/commands/list_commands.js.map +0 -1
  766. package/node_modules/remote-pi/dist/config.d.ts +0 -62
  767. package/node_modules/remote-pi/dist/config.js +0 -115
  768. package/node_modules/remote-pi/dist/config.js.map +0 -1
  769. package/node_modules/remote-pi/dist/daemon/client.d.ts +0 -20
  770. package/node_modules/remote-pi/dist/daemon/client.js +0 -131
  771. package/node_modules/remote-pi/dist/daemon/client.js.map +0 -1
  772. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +0 -176
  773. package/node_modules/remote-pi/dist/daemon/control_protocol.js +0 -63
  774. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +0 -1
  775. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +0 -45
  776. package/node_modules/remote-pi/dist/daemon/cron_log.js +0 -72
  777. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +0 -1
  778. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +0 -80
  779. package/node_modules/remote-pi/dist/daemon/cron_registry.js +0 -194
  780. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +0 -1
  781. package/node_modules/remote-pi/dist/daemon/id.d.ts +0 -24
  782. package/node_modules/remote-pi/dist/daemon/id.js +0 -36
  783. package/node_modules/remote-pi/dist/daemon/id.js.map +0 -1
  784. package/node_modules/remote-pi/dist/daemon/install.d.ts +0 -170
  785. package/node_modules/remote-pi/dist/daemon/install.js +0 -547
  786. package/node_modules/remote-pi/dist/daemon/install.js.map +0 -1
  787. package/node_modules/remote-pi/dist/daemon/registry.d.ts +0 -63
  788. package/node_modules/remote-pi/dist/daemon/registry.js +0 -153
  789. package/node_modules/remote-pi/dist/daemon/registry.js.map +0 -1
  790. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +0 -194
  791. package/node_modules/remote-pi/dist/daemon/rpc_child.js +0 -389
  792. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +0 -1
  793. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +0 -93
  794. package/node_modules/remote-pi/dist/daemon/supervisor.js +0 -596
  795. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +0 -1
  796. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +0 -26
  797. package/node_modules/remote-pi/dist/extension_ui_bridge.js +0 -341
  798. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +0 -1
  799. package/node_modules/remote-pi/dist/index.d.ts +0 -213
  800. package/node_modules/remote-pi/dist/index.js +0 -4996
  801. package/node_modules/remote-pi/dist/index.js.map +0 -1
  802. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +0 -10
  803. package/node_modules/remote-pi/dist/mcp/mesh_result.js +0 -42
  804. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +0 -1
  805. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +0 -16
  806. package/node_modules/remote-pi/dist/mcp/mesh_server.js +0 -327
  807. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +0 -1
  808. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +0 -30
  809. package/node_modules/remote-pi/dist/mesh/canonical.js +0 -61
  810. package/node_modules/remote-pi/dist/mesh/canonical.js.map +0 -1
  811. package/node_modules/remote-pi/dist/mesh/client.d.ts +0 -18
  812. package/node_modules/remote-pi/dist/mesh/client.js +0 -125
  813. package/node_modules/remote-pi/dist/mesh/client.js.map +0 -1
  814. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +0 -38
  815. package/node_modules/remote-pi/dist/mesh/encoding.js +0 -216
  816. package/node_modules/remote-pi/dist/mesh/encoding.js.map +0 -1
  817. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +0 -73
  818. package/node_modules/remote-pi/dist/mesh/self_revoke.js +0 -401
  819. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +0 -1
  820. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +0 -49
  821. package/node_modules/remote-pi/dist/mesh/siblings.js +0 -159
  822. package/node_modules/remote-pi/dist/mesh/siblings.js.map +0 -1
  823. package/node_modules/remote-pi/dist/mesh/types.d.ts +0 -34
  824. package/node_modules/remote-pi/dist/mesh/types.js +0 -11
  825. package/node_modules/remote-pi/dist/mesh/types.js.map +0 -1
  826. package/node_modules/remote-pi/dist/mesh/verify.d.ts +0 -17
  827. package/node_modules/remote-pi/dist/mesh/verify.js +0 -86
  828. package/node_modules/remote-pi/dist/mesh/verify.js.map +0 -1
  829. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +0 -8
  830. package/node_modules/remote-pi/dist/pairing/crypto.js +0 -22
  831. package/node_modules/remote-pi/dist/pairing/crypto.js.map +0 -1
  832. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +0 -28
  833. package/node_modules/remote-pi/dist/pairing/handshake.js +0 -113
  834. package/node_modules/remote-pi/dist/pairing/handshake.js.map +0 -1
  835. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +0 -16
  836. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +0 -103
  837. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +0 -1
  838. package/node_modules/remote-pi/dist/pairing/qr.d.ts +0 -59
  839. package/node_modules/remote-pi/dist/pairing/qr.js +0 -125
  840. package/node_modules/remote-pi/dist/pairing/qr.js.map +0 -1
  841. package/node_modules/remote-pi/dist/pairing/storage.d.ts +0 -120
  842. package/node_modules/remote-pi/dist/pairing/storage.js +0 -604
  843. package/node_modules/remote-pi/dist/pairing/storage.js.map +0 -1
  844. package/node_modules/remote-pi/dist/protocol/codec.d.ts +0 -7
  845. package/node_modules/remote-pi/dist/protocol/codec.js +0 -49
  846. package/node_modules/remote-pi/dist/protocol/codec.js.map +0 -1
  847. package/node_modules/remote-pi/dist/protocol/types.d.ts +0 -393
  848. package/node_modules/remote-pi/dist/protocol/types.js +0 -2
  849. package/node_modules/remote-pi/dist/protocol/types.js.map +0 -1
  850. package/node_modules/remote-pi/dist/rooms.d.ts +0 -29
  851. package/node_modules/remote-pi/dist/rooms.js +0 -57
  852. package/node_modules/remote-pi/dist/rooms.js.map +0 -1
  853. package/node_modules/remote-pi/dist/session/address.d.ts +0 -49
  854. package/node_modules/remote-pi/dist/session/address.js +0 -58
  855. package/node_modules/remote-pi/dist/session/address.js.map +0 -1
  856. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +0 -55
  857. package/node_modules/remote-pi/dist/session/agent_bridge.js +0 -146
  858. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +0 -1
  859. package/node_modules/remote-pi/dist/session/bridge.d.ts +0 -37
  860. package/node_modules/remote-pi/dist/session/bridge.js +0 -130
  861. package/node_modules/remote-pi/dist/session/bridge.js.map +0 -1
  862. package/node_modules/remote-pi/dist/session/broker.d.ts +0 -189
  863. package/node_modules/remote-pi/dist/session/broker.js +0 -507
  864. package/node_modules/remote-pi/dist/session/broker.js.map +0 -1
  865. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +0 -74
  866. package/node_modules/remote-pi/dist/session/broker_remote.js +0 -583
  867. package/node_modules/remote-pi/dist/session/broker_remote.js.map +0 -1
  868. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +0 -33
  869. package/node_modules/remote-pi/dist/session/cwd_lock.js +0 -126
  870. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +0 -1
  871. package/node_modules/remote-pi/dist/session/envelope.d.ts +0 -33
  872. package/node_modules/remote-pi/dist/session/envelope.js +0 -117
  873. package/node_modules/remote-pi/dist/session/envelope.js.map +0 -1
  874. package/node_modules/remote-pi/dist/session/global_config.d.ts +0 -33
  875. package/node_modules/remote-pi/dist/session/global_config.js +0 -73
  876. package/node_modules/remote-pi/dist/session/global_config.js.map +0 -1
  877. package/node_modules/remote-pi/dist/session/ipc.d.ts +0 -27
  878. package/node_modules/remote-pi/dist/session/ipc.js +0 -22
  879. package/node_modules/remote-pi/dist/session/ipc.js.map +0 -1
  880. package/node_modules/remote-pi/dist/session/leader_election.d.ts +0 -32
  881. package/node_modules/remote-pi/dist/session/leader_election.js +0 -106
  882. package/node_modules/remote-pi/dist/session/leader_election.js.map +0 -1
  883. package/node_modules/remote-pi/dist/session/local_config.d.ts +0 -55
  884. package/node_modules/remote-pi/dist/session/local_config.js +0 -157
  885. package/node_modules/remote-pi/dist/session/local_config.js.map +0 -1
  886. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +0 -20
  887. package/node_modules/remote-pi/dist/session/mesh_message.js +0 -28
  888. package/node_modules/remote-pi/dist/session/mesh_message.js.map +0 -1
  889. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +0 -116
  890. package/node_modules/remote-pi/dist/session/mesh_node.js +0 -573
  891. package/node_modules/remote-pi/dist/session/mesh_node.js.map +0 -1
  892. package/node_modules/remote-pi/dist/session/peer.d.ts +0 -139
  893. package/node_modules/remote-pi/dist/session/peer.js +0 -451
  894. package/node_modules/remote-pi/dist/session/peer.js.map +0 -1
  895. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +0 -13
  896. package/node_modules/remote-pi/dist/session/peer_inventory.js +0 -48
  897. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +0 -1
  898. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +0 -9
  899. package/node_modules/remote-pi/dist/session/peer_limits.js +0 -21
  900. package/node_modules/remote-pi/dist/session/peer_limits.js.map +0 -1
  901. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +0 -39
  902. package/node_modules/remote-pi/dist/session/setup_wizard.js +0 -63
  903. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +0 -1
  904. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +0 -5
  905. package/node_modules/remote-pi/dist/session/tool_gate.js +0 -11
  906. package/node_modules/remote-pi/dist/session/tool_gate.js.map +0 -1
  907. package/node_modules/remote-pi/dist/session/tools.d.ts +0 -24
  908. package/node_modules/remote-pi/dist/session/tools.js +0 -252
  909. package/node_modules/remote-pi/dist/session/tools.js.map +0 -1
  910. package/node_modules/remote-pi/dist/session/wizard.d.ts +0 -13
  911. package/node_modules/remote-pi/dist/session/wizard.js +0 -20
  912. package/node_modules/remote-pi/dist/session/wizard.js.map +0 -1
  913. package/node_modules/remote-pi/dist/settings.d.ts +0 -15
  914. package/node_modules/remote-pi/dist/settings.js +0 -52
  915. package/node_modules/remote-pi/dist/settings.js.map +0 -1
  916. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +0 -37
  917. package/node_modules/remote-pi/dist/transport/peer_channel.js +0 -98
  918. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +0 -1
  919. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +0 -29
  920. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +0 -62
  921. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +0 -1
  922. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +0 -91
  923. package/node_modules/remote-pi/dist/transport/relay_client.js +0 -206
  924. package/node_modules/remote-pi/dist/transport/relay_client.js.map +0 -1
  925. package/node_modules/remote-pi/dist/ui/footer.d.ts +0 -32
  926. package/node_modules/remote-pi/dist/ui/footer.js +0 -34
  927. package/node_modules/remote-pi/dist/ui/footer.js.map +0 -1
  928. package/node_modules/remote-pi/docs/daemon.md +0 -289
  929. package/node_modules/remote-pi/package.json +0 -92
  930. package/node_modules/remote-pi/service-templates/launchd.plist.template +0 -35
  931. package/node_modules/remote-pi/service-templates/systemd.service.template +0 -19
  932. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +0 -10
  933. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +0 -38
  934. package/node_modules/remote-pi/skills/agent-network/SKILL.md +0 -310
@@ -1,1745 +0,0 @@
1
- /**
2
- * lsp_diagnostics tool definition
3
- *
4
- * Proactive LSP diagnostics check — single files or directories.
5
- * Adopted from code-yeongyu/pi-lsp-client design.
6
- */
7
- import * as fs from "node:fs";
8
- import * as path from "node:path";
9
- import { getProjectIgnoreMatcher, isExcludedDirName, } from "../clients/file-utils.js";
10
- import { getLSPService, groupFilesByPrimaryServer, runPerServerGroups, } from "../clients/lsp/index.js";
11
- import { buildScopeKey, createWorkspaceDiagnosticsCacheContext, } from "../clients/lsp/workspace-diagnostics-cache.js";
12
- import { getServersForFileWithConfig, primaryServerId, } from "../clients/lsp/config.js";
13
- import { mapWithConcurrency } from "../clients/map-with-concurrency.js";
14
- import { combineAbortSignals, withDeadline, } from "../clients/deadline-utils.js";
15
- import { applyAuxiliarySuppressions, retagAuxiliaryDiagnostics, } from "../clients/dispatch/auxiliary-lsp.js";
16
- import { applyLspFindingPolicy, loadProjectRulePolicyMap, } from "../clients/dispatch/finding-policy.js";
17
- import { hasStrictDispositionMarks } from "../clients/diagnostic-dispositions.js";
18
- import { recordDegradationOnce } from "../clients/degradation-ledger.js";
19
- import { logLatency } from "../clients/latency-logger.js";
20
- import { detectFileRole } from "../clients/file-role.js";
21
- import { hashDiagnosticContent, touchCompletedConfirmationPolicy, touchCoverageGap, } from "../clients/lsp/diagnostic-binding.js";
22
- import { classifyCascadeWaitTier } from "../clients/lsp/wait-policy/index.js";
23
- import { attemptTsserverSyncDiagnostics } from "../clients/lsp/tsserver-sync.js";
24
- import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
25
- import { demoteInferredProjectDiagnostics } from "../clients/lsp/inferred-project.js";
26
- import { normalizeMapKey } from "../clients/path-utils.js";
27
- import { countRetainedSuppressedRows, isBlocking, reconcileScanDiagnostics, } from "../clients/widget-state.js";
28
- import { makeProgressReporter } from "./scan-progress.js";
29
- import { isWarmAttached, tryWarmAttachedDiagnostics, } from "../clients/warm-attach.js";
30
- import { extensionsForLanguage, SCAN_LANGUAGE_PRIORITY, } from "../clients/language-registry.js";
31
- import { exceedsLspSyncLimits } from "../clients/lsp/content-limits.js";
32
- const MAX_FILES = 100;
33
- export const MAX_BATCH_FILES = 100;
34
- const MAX_DIAGNOSTICS = 200;
35
- const DEFAULT_BATCH_CONCURRENCY = 8;
36
- const MAX_BATCH_CONCURRENCY = 16;
37
- const DEFAULT_BATCH_FILE_DEADLINE_MS = 15_000;
38
- // LSP severities: 1=Error, 2=Warning, 3=Information, 4=Hint
39
- export const SEVERITY_NAMES = {
40
- 1: "error",
41
- 2: "warning",
42
- 3: "information",
43
- 4: "hint",
44
- };
45
- export const LSP_SEVERITY_FILTERS = [
46
- ...Object.values(SEVERITY_NAMES),
47
- "all",
48
- ];
49
- function assertNeverBatchFileOutcome(value) {
50
- throw new Error(`Unhandled batch file outcome: ${String(value)}`);
51
- }
52
- /** Render the bounded per-file outcomes shared by batch, directory, and fold surfaces. */
53
- export function renderBatchOutcomeLines(outcomes, formatFile = (file) => file) {
54
- const lines = [];
55
- for (const outcome of outcomes) {
56
- switch (outcome.outcome) {
57
- case "too_large":
58
- lines.push(`${formatFile(outcome.file)}: ${outcome.reason ?? "file too large for LSP diagnostics"}`);
59
- break;
60
- case "clean":
61
- case "findings":
62
- case "unsupported":
63
- case "unavailable":
64
- case "failed":
65
- case "inconclusive":
66
- break;
67
- default:
68
- assertNeverBatchFileOutcome(outcome.outcome);
69
- }
70
- }
71
- return lines;
72
- }
73
- function batchFileDeadlineMs() {
74
- const raw = Number(process.env.PI_LENS_LSP_BATCH_FILE_MS);
75
- return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_BATCH_FILE_DEADLINE_MS;
76
- }
77
- // #646: `primaryServerId` moved to clients/lsp/config.ts so this tool and
78
- // tools/lens-diagnostics.ts's mode=full sweep share the exact same
79
- // primary-vs-auxiliary classification instead of each keeping its own copy.
80
- function lspUnavailableMessage(filePath, health) {
81
- if (!health || !String(health.health ?? "").startsWith("no_clients")) {
82
- return undefined;
83
- }
84
- const candidates = health.candidateServerIds?.length
85
- ? ` candidates=${health.candidateServerIds.join(",")}`
86
- : "";
87
- const reason = (health.serverCountAttempted ?? 0) === 0
88
- ? "no LSP server configured"
89
- : "no LSP client is currently ready";
90
- const stale = (health.mergedCount ?? 0) > 0
91
- ? " Showing stale last-known diagnostics below."
92
- : " No diagnostics were collected.";
93
- return `LSP unavailable for ${filePath}: ${reason}; ready=${health.serverCountReady ?? 0}/${health.serverCountAttempted ?? 0}.${candidates}.${stale}`;
94
- }
95
- function boundedPositiveInt(value, fallback, min, max) {
96
- const parsed = typeof value === "number" ? Math.floor(value) : Number.NaN;
97
- if (!Number.isFinite(parsed))
98
- return fallback;
99
- return Math.max(min, Math.min(max, parsed));
100
- }
101
- /**
102
- * #631: fan `mapper` out across `items` (a batch/directory file list) while
103
- * respecting per-LSP-server affinity — previously this was a flat,
104
- * server-oblivious bounded-concurrency pool (up to `concurrency` files
105
- * in flight at once, regardless of which server they belonged to). That let
106
- * a single-language batch (the common case) fire many concurrent touches at
107
- * the SAME shared, single-threaded LSP server — exactly the pattern #387
108
- * found doesn't parallelize (it queues server-side and cascades per-file
109
- * timeouts by queue position) and that `runWorkspaceDiagnostics` (the engine
110
- * behind `lens_diagnostics mode=full`) has been protected against since #387.
111
- *
112
- * Groups `items` by primary server via `groupFilesByPrimaryServer` (the same
113
- * grouping key `runWorkspaceDiagnostics` uses) and schedules them with
114
- * `runPerServerGroups` (both extracted from `clients/lsp/index.ts` so this
115
- * tool shares the real primitive instead of a second hand-copied
116
- * implementation): at most one in-flight `mapper` call per server group,
117
- * parallelized across distinct groups up to `concurrency`. A single-language
118
- * batch collapses to one group and runs effectively serially regardless of
119
- * `concurrency` — the CORRECT, intended #387 behavior, not a regression.
120
- *
121
- * Result order matches `items`' original order (not completion order),
122
- * matching the old flat pool's positional-assignment behavior — callers may
123
- * depend on `results[i]` corresponding to `items[i]`.
124
- *
125
- * #667: before a group's own per-file loop starts, calls the shared
126
- * `LSPService.ensureWarmForSweep` warm-check/ensure-warm step (the same one
127
- * `runWorkspaceDiagnostics` uses for `lens_diagnostics mode=full`) against
128
- * the group's first file — a no-op when that group's primary server already
129
- * demonstrated readiness earlier this session, one bounded warm-up round
130
- * trip otherwise. Fixes the first-few-files-eat-cold-start-timeouts pattern
131
- * for THIS tool's batch/directory sweep the same way #667 fixed it for the
132
- * workspace-diagnostics sweep.
133
- */
134
- /**
135
- * Project-ignore predicate rooted at `root`, fail-open. Lets a directory scan
136
- * honor the user's `.pi-lens.json` / `.gitignore` patterns — not just the
137
- * canonical dir-name list — so `lsp_diagnostics` stays consistent with the
138
- * workspace-diagnostics walk and every other scan surface (#243/#297/#298). A
139
- * config-probe error never blocks a scan (matches the walkers' behaviour).
140
- */
141
- function projectIgnorePredicate(root) {
142
- try {
143
- const matcher = getProjectIgnoreMatcher(root);
144
- return (fullPath, isDir) => matcher.isIgnored(fullPath, isDir);
145
- }
146
- catch {
147
- return () => false;
148
- }
149
- }
150
- /**
151
- * #1137: async so a directory read never blocks the event loop (and pi's TUI).
152
- *
153
- * This walk was fully synchronous with NO yielding of any kind, bounded only by
154
- * `maxFiles` *kept* — an ignored-heavy or cloud-backed (OneDrive/network) tree
155
- * could traverse unboundedly many entries, and a single stalled `readdirSync`
156
- * held the loop for the whole stall. It is also called once PER FAMILY in
157
- * `runDirectoryDiagnostics`'s `SCAN_LANGUAGE_PRIORITY` loop (#2434, grouped by
158
- * family since #2458 fix-round F1), so a directory-mode `lsp_diagnostics`
159
- * could pay that cost several times over.
160
- *
161
- * The traversal is deliberately still **depth-first with immediate descent**
162
- * (not the shared stack-based `walkTreeStackAsync`): the `maxFiles` cap makes
163
- * traversal ORDER observable — a stack walk would keep a different subset of
164
- * files on an over-large tree. Only scheduling changes here; the returned list
165
- * is identical. Awaiting each directory read is itself the yield point.
166
- */
167
- async function collectFiles(dir, extensions, maxFiles, isIgnored = () => false) {
168
- const files = [];
169
- async function walk(current) {
170
- if (files.length >= maxFiles)
171
- return;
172
- let entries;
173
- try {
174
- entries = await fs.promises.readdir(current, { withFileTypes: true });
175
- }
176
- catch {
177
- return;
178
- }
179
- for (const entry of entries) {
180
- if (files.length >= maxFiles)
181
- return;
182
- if (entry.isSymbolicLink())
183
- continue;
184
- const full = path.join(current, entry.name);
185
- if (entry.isDirectory()) {
186
- if (!isExcludedDirName(entry.name) && !isIgnored(full, true))
187
- await walk(full);
188
- }
189
- else if (entry.isFile() && extensions.includes(path.extname(full))) {
190
- if (isIgnored(full, false))
191
- continue;
192
- files.push(full);
193
- }
194
- }
195
- }
196
- await walk(dir);
197
- return files;
198
- }
199
- export function createLspDiagnosticsTool(
200
- // #571/#1198: same shared write-ordering token source `lens_diagnostics`
201
- // mode=full uses (index.ts injects `() => runtime.nextWriteIndex()`). A
202
- // confirmed result reconciled into the footer reserves its token when the
203
- // per-file check starts, so settlement order cannot make an older result look
204
- // newer. Optional/undefined in tests.
205
- nextWriteIndex,
206
- // #1561: #571 wired this tool's confirmed result into the widget footer and
207
- // stopped there. The inline-blocker map is a SECOND agent-facing store fed by
208
- // the same dispatch verdict, and nothing retired it — so pi-lens kept
209
- // injecting "Unresolved from this turn" for three more turns after answering
210
- // "confirmed clean" for the same file. index.ts injects
211
- // `runtime.retireInlineBlockerOnConfirmedClean`. Optional/undefined in tests.
212
- onConfirmedNoBlockers, getService = getLSPService) {
213
- return {
214
- async execute(_toolCallId, params, _signal, onUpdate, ctx) {
215
- // Escape aborts the turn via ctx.signal; honor both it and the tool-call
216
- // signal so a batch/directory scan cancels rather than grinding on.
217
- const signal = combineAbortSignals(_signal, ctx.signal);
218
- // Stream a throttled progress bar for batch/directory scans (opaque for
219
- // seconds-to-minutes otherwise).
220
- const onProgress = makeProgressReporter(onUpdate, "Scanning LSP diagnostics");
221
- const typedParams = params;
222
- const severity = (typedParams.severity ?? "all");
223
- const cwd = ctx.cwd ?? process.cwd();
224
- const concurrency = boundedPositiveInt(typedParams.concurrency, DEFAULT_BATCH_CONCURRENCY, 1, MAX_BATCH_CONCURRENCY);
225
- const waitMs = typeof typedParams.waitMs === "number" && typedParams.waitMs >= 0
226
- ? Math.floor(typedParams.waitMs)
227
- : undefined;
228
- const serverScope = typedParams.serverScope === "primary" ? "primary" : "all";
229
- const lspService = getService();
230
- if (!lspService) {
231
- return {
232
- content: [
233
- { type: "text", text: "LSP service not available." },
234
- ],
235
- isError: true,
236
- details: {},
237
- };
238
- }
239
- if (Array.isArray(typedParams.paths) && typedParams.paths.length > 0) {
240
- if (typedParams.paths.length > MAX_BATCH_FILES) {
241
- return {
242
- content: [
243
- {
244
- type: "text",
245
- text: `paths accepts at most ${MAX_BATCH_FILES} files; received ${typedParams.paths.length}.`,
246
- },
247
- ],
248
- isError: true,
249
- details: { mode: "batch", filesChecked: 0 },
250
- };
251
- }
252
- const rawPaths = typedParams.paths.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
253
- if (rawPaths.length !== typedParams.paths.length) {
254
- return {
255
- content: [
256
- {
257
- type: "text",
258
- text: "paths must contain non-empty file paths.",
259
- },
260
- ],
261
- isError: true,
262
- details: { mode: "batch", filesChecked: 0 },
263
- };
264
- }
265
- // Preserve input order (including duplicate entries); normalize each
266
- // path before grouping so Windows separators and dot segments cannot
267
- // change cache/group identity. Explicit lists never enter the walker.
268
- // #3160/#3182: `path.resolve(cwd, entry)` folds dot segments (and
269
- // separators) structurally — it ignores `cwd` whenever `entry` is
270
- // already absolute, so the old `path.isAbsolute` ternary is
271
- // redundant. `normalizeMapKey` then adopts on-disk CASING where the
272
- // path exists — an agent-typed, possibly mis-cased `paths` entry
273
- // must key `reconcileScanDiagnostics`'s widget-state write the same
274
- // way a canonical writer (clients/pipeline.ts's ctx.filePath) or the
275
- // #3160-fixed lens_diagnostic_mark reader would. `path.resolve`
276
- // stays required for the relative→absolute step: `normalizeMapKey`
277
- // folds dot segments itself since #3184, but never resolves against
278
- // `cwd` (a cwd fold there broke every monorepo, #2490).
279
- const absPaths = rawPaths.map((entry) => normalizeMapKey(path.resolve(cwd, entry)));
280
- return runBatchFileDiagnostics(absPaths, severity, lspService, {
281
- concurrency,
282
- waitMs,
283
- signal,
284
- onProgress,
285
- nextWriteIndex,
286
- serverScope,
287
- cwd,
288
- onConfirmedNoBlockers,
289
- });
290
- }
291
- const rawPath = typedParams.path;
292
- if (!rawPath || rawPath.trim().length === 0) {
293
- return {
294
- content: [
295
- {
296
- type: "text",
297
- text: "path or paths is required.",
298
- },
299
- ],
300
- isError: true,
301
- details: {},
302
- };
303
- }
304
- // #3184: the single-`path` sibling of the `paths` batch above, and
305
- // keyed the same way — `runFileDiagnostics` hands this straight to
306
- // `reconcileScanDiagnostics`, whose `normalizeEphemeralMapKey` key
307
- // derivation folds neither dot segments nor casing. Same expression as
308
- // :444 so both modes of this tool write under ONE key per file.
309
- const absPath = normalizeMapKey(path.resolve(cwd, rawPath));
310
- let stat;
311
- try {
312
- stat = fs.statSync(absPath);
313
- }
314
- catch {
315
- return {
316
- content: [
317
- { type: "text", text: `Path not found: ${absPath}` },
318
- ],
319
- isError: true,
320
- details: {},
321
- };
322
- }
323
- if (stat.isDirectory()) {
324
- return runDirectoryDiagnostics(absPath, severity, lspService, {
325
- concurrency,
326
- waitMs,
327
- signal,
328
- onProgress,
329
- nextWriteIndex,
330
- serverScope,
331
- cwd,
332
- onConfirmedNoBlockers,
333
- });
334
- }
335
- return runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope, cwd, onConfirmedNoBlockers);
336
- },
337
- };
338
- }
339
- async function collectDiagnosticsForFile(absPath, lspService,
340
- /**
341
- * #3041: project root the per-rule `ignores` globs (#965) are resolved
342
- * against. ast-grep's LSP publishes per-document diagnostics without
343
- * applying them, so this standalone `source=lsp` query has to — the same
344
- * carve-out the NAPI runner applies on the same file. Positioned before the
345
- * optional parameters so it is structurally REQUIRED: an optional
346
- * `string | undefined` would silently disable the carve-out for whichever
347
- * caller forgot to pass it.
348
- */
349
- scanRoot, waitMs, serverScope = "all") {
350
- let timedOut = false;
351
- let content;
352
- // `touchFile` is the authoritative collection boundary for every scope: it
353
- // preserves per-touch timeout, content-binding, and silent-clean confirmation
354
- // metadata while returning diagnostics from only the requested clients. The
355
- // getDiagnostics fallback below remains for the two states a REAL service
356
- // still reaches: the file read threw (no content to touch with), or the
357
- // touch resolved no clients and returned `undefined` (clients/lsp/index.ts
358
- // `touchFile`'s `no_clients`/`destroyed` returns). #2598 deleted the third
359
- // reason — "an older/mock service without touchFile" — because the real
360
- // `LSPService` has always defined the method unconditionally, so that arm
361
- // was reachable only from a partial test double (AGENTS.md shape 7).
362
- // #1179: the result is an explicit wrapper so side-channel fields survive
363
- // array copies; confirmation was added when Marksman's lower-level clean verdict
364
- // proved that a successful empty collection also needs explicit provenance.
365
- let touched;
366
- try {
367
- content = fs.readFileSync(absPath, "utf-8");
368
- const contentLimit = exceedsLspSyncLimits(content);
369
- if (contentLimit.tooLarge) {
370
- const reason = `file too large for LSP diagnostics (${contentLimit.reason})`;
371
- recordDegradationOnce({
372
- kind: "lsp-diagnostics-file-too-large",
373
- subject: absPath,
374
- reason,
375
- });
376
- return {
377
- diagnostics: [],
378
- timedOut: false,
379
- confirmedByTouch: false,
380
- unconfirmedServerIds: [],
381
- diagnosticsUnsupportedServerIds: [],
382
- content,
383
- tooLargeReason: reason,
384
- };
385
- }
386
- if (isWarmAttached()) {
387
- // The local sweep's default service wait is bounded to the same
388
- // 15-second per-file envelope used by the workspace sweep. An explicit
389
- // waitMs remains the tighter caller-selected cap.
390
- const attachedBudgetMs = waitMs ?? 15_000;
391
- const attached = await tryWarmAttachedDiagnostics(absPath, content, attachedBudgetMs, "sweep");
392
- if (attached?.available) {
393
- const scopedDiagnostics = serverScope === "primary"
394
- ? attached.response.diagnostics.filter((item) => item.serverId === primaryServerId(absPath))
395
- : attached.response.diagnostics;
396
- const filtered = applyAuxiliarySuppressions(scopedDiagnostics, content, {
397
- fileRole: detectFileRole(absPath, content),
398
- filePath: absPath,
399
- scanRoot,
400
- });
401
- return {
402
- diagnostics: filtered,
403
- timedOut: false,
404
- // #1253: the incumbent's touch carries the same confirmation
405
- // provenance a local touch does (an `available: true` answer is
406
- // already gated on `fresh && !inconclusive`, but that is NOT
407
- // evidence a silent-on-clean server was confirmed — only the
408
- // explicit flag is). The incumbent always touches with
409
- // `clientScope: "with-auxiliary"`, so this is an AGGREGATE
410
- // confirmation: it carries the same caveat all-scope local
411
- // touches do, and classic TypeScript still needs the primary-only
412
- // tsserver sync check below rather than this verdict.
413
- // #1470: `"partial"` counts, for the same reason the local touch
414
- // branch below accepts it — the incumbent's primary confirmed; only
415
- // a named auxiliary did not.
416
- confirmedByTouch: attached.response.confirmation !== undefined &&
417
- primaryServerId(absPath) !== "typescript",
418
- // #1470: the incumbent's narrowed verdict, carried as an explicit DTO
419
- // field across the socket. An older incumbent omits it → empty → the
420
- // pre-#1470 handling, unchanged.
421
- unconfirmedServerIds: attached.response.unconfirmedServerIds ?? [],
422
- diagnosticsUnsupportedServerIds: [],
423
- content,
424
- };
425
- }
426
- }
427
- touched = await lspService.touchFile(absPath, content, {
428
- diagnostics: "document",
429
- collectDiagnostics: true,
430
- maxClientWaitMs: waitMs,
431
- source: "lsp_diagnostics",
432
- clientScope: serverScope,
433
- // #3405: the caller asked whether THIS file is clean right now, and the
434
- // content above was just read from disk — so it is the file's saved
435
- // state. Without the save a save-triggered server answers zero
436
- // diagnostics for every file in the query, which this path would report
437
- // as clean.
438
- saved: true,
439
- });
440
- timedOut = touched?.inconclusive === true;
441
- }
442
- catch {
443
- // Non-fatal: getDiagnostics may still have stale/health information.
444
- }
445
- // Only fall through to the unscoped getDiagnostics() read when the touch
446
- // produced nothing to read — it threw, the file read threw before it ran, or
447
- // it resolved no clients at all. When touched IS defined it's already the
448
- // answer — reusing it is what makes serverScope:"primary" actually skip
449
- // auxiliary scanners and drops the common case back to a single LSP round
450
- // trip instead of two.
451
- const diagnostics = touched !== undefined
452
- ? touched.diags
453
- : await lspService.getDiagnostics(absPath, waitMs !== undefined ? "document" : "full");
454
- // #586: honor each auxiliary profile's native inline-suppression comment
455
- // (e.g. opengrep's `// nosemgrep`, #441) the same way the per-edit dispatch
456
- // runner does — previously this standalone query path ignored it entirely.
457
- // #692: also honor a profile's `skipTestFiles` gate (e.g. ast-grep, #687) —
458
- // this standalone-query path had no test-file gating of its own, so an
459
- // `lsp_diagnostics` check on a test file surfaced ast-grep findings the
460
- // per-edit dispatch runner would have suppressed. `content` is only unset
461
- // if the read itself failed above; fail-open (no filtering) rather than
462
- // lose diagnostics over an unrelated read error.
463
- const filtered = content !== undefined
464
- ? applyAuxiliarySuppressions(diagnostics, content, {
465
- fileRole: detectFileRole(absPath, content),
466
- filePath: absPath,
467
- scanRoot,
468
- })
469
- : diagnostics;
470
- // #1095: surface the touch's content binding (only a touch that resolved
471
- // clients carries one; the getDiagnostics fallback leaves it undefined →
472
- // "unknown", no demotion).
473
- const binding = touched?.binding;
474
- // #1470: `"partial"` counts here. `confirmedByTouch` feeds
475
- // `canTrustTouchConfirmation`, which asks about the PRIMARY's own verdict —
476
- // and a partial touch is one whose primary confirmed while an auxiliary was
477
- // cut off. Excluding it would render "Primary LSP: unconfirmed" for a primary
478
- // that did confirm. The coverage gap is carried separately, below.
479
- const confirmedByTouch = touchCompletedConfirmationPolicy(touched);
480
- return {
481
- diagnostics: filtered,
482
- timedOut,
483
- skipReason: touched?.skipReason,
484
- confirmedByTouch,
485
- // #1470: only a touch that resolved clients contributes a coverage gap;
486
- // the getDiagnostics fallback never reports one, which is honest — that
487
- // path claims no confirmation at all.
488
- unconfirmedServerIds: touchCoverageGap(touched),
489
- diagnosticsUnsupportedServerIds: touched?.diagnosticsUnsupportedServerIds ?? [],
490
- content,
491
- binding,
492
- };
493
- }
494
- function diagnosticsToFileDiags(file, diagnostics) {
495
- return diagnostics.map((d) => ({
496
- file,
497
- line: d.range?.start?.line,
498
- character: d.range?.start?.character,
499
- severity: d.severity,
500
- message: d.message,
501
- source: d.source,
502
- serverId: d.serverId,
503
- code: d.code,
504
- }));
505
- }
506
- /**
507
- * #533: classify an EMPTY diagnostic result as "clean" (the server actually
508
- * confirmed no issues) or "unconfirmed" (came from a push-only,
509
- * silent-on-clean server — classic typescript-language-server — that
510
- * publishes nothing on a clean→clean transition, so an empty result here is
511
- * indistinguishable from "still analyzing" or "never asked"). Reuses the same
512
- * capability-snapshot classifier the #458 cascade lane already trusts
513
- * (`classifyCascadeWaitTier`) so this tool's notion of "silent tier-3" stays
514
- * in lockstep with the rest of the LSP layer instead of drifting via a second
515
- * copy of the server-strategy table. Fail-safe: any error or missing snapshot
516
- * (server not alive, capability probe failure) reads as "clean" — the same
517
- * default this tool has always had — rather than manufacturing a new failure
518
- * mode from a best-effort classification.
519
- */
520
- async function classifyEmptyResult(file, lspService) {
521
- try {
522
- const snapshots = await lspService.getCapabilitySnapshots(file);
523
- const tier = classifyCascadeWaitTier(lspService, file, snapshots);
524
- return tier === "tier3-silent" ? "unconfirmed" : "clean";
525
- }
526
- catch {
527
- return "clean";
528
- }
529
- }
530
- // --- #611/#707: tier-3 silent escape hatch (typescript.tsserverRequest sync
531
- // commands) — implementation extracted to clients/lsp/tsserver-sync.ts and
532
- // re-used from there by the per-edit dispatch path (#707). ---
533
- /**
534
- * #611: resolve an EMPTY diagnostic result for a Tier-3 silent server (see
535
- * `classifyCascadeWaitTier` — today only classic typescript-language-server,
536
- * native-ts7 is explicitly excluded there) with a definitive answer instead of
537
- * defaulting straight to "unconfirmed". `confirmed: true` with an empty
538
- * `diagnostics` array is a genuinely confirmed clean result; `confirmed: true`
539
- * with a non-empty array means the sync command surfaced real diagnostics the
540
- * server had computed but never published (silentOnClean) — these must be
541
- * surfaced to the caller, not discarded. `confirmed: false` is the existing
542
- * "unconfirmed" fallback (command unavailable, error, or the file isn't part
543
- * of any project). Fail-safe: any error in the tier classification itself
544
- * (missing snapshot, server not alive) reads as `confirmed: true` with no
545
- * diagnostics — the same "clean" default this tool has always had.
546
- */
547
- async function resolveEmptyResult(file, lspService) {
548
- try {
549
- const snapshots = await lspService.getCapabilitySnapshots(file);
550
- const tier = classifyCascadeWaitTier(lspService, file, snapshots);
551
- if (tier !== "tier3-silent") {
552
- return { confirmed: true, diagnostics: [] };
553
- }
554
- const syncDiagnostics = await attemptTsserverSyncDiagnostics(file, lspService);
555
- if (syncDiagnostics === undefined) {
556
- return { confirmed: false, diagnostics: [] };
557
- }
558
- return { confirmed: true, diagnostics: syncDiagnostics };
559
- }
560
- catch {
561
- return { confirmed: true, diagnostics: [] };
562
- }
563
- }
564
- /**
565
- * A primary-scope touch is authoritative because `touchFile` runs that
566
- * primary's own confirmation path (including TypeScript's sync fallback). For
567
- * all-scope TypeScript touches, the aggregate silent-clean gate can settle
568
- * without that primary-only sync request, so preserve `resolveEmptyResult`'s
569
- * existing tsserver fallback instead of accepting the aggregate verdict.
570
- */
571
- function canTrustTouchConfirmation(file, serverScope, confirmedByTouch) {
572
- return (confirmedByTouch &&
573
- (serverScope === "primary" || primaryServerId(file) !== "typescript"));
574
- }
575
- /**
576
- * #1561 F1: what this check is entitled to speak for.
577
- *
578
- * Inline blockers are raised by the whole dispatch — eslint, biome-check,
579
- * actionlint, ast-grep security rules — while this tool only ever consults
580
- * language servers. Retiring one therefore needs an explicit coverage claim,
581
- * and the honest claim is exactly the servers this check consulted and got an
582
- * answer from. `serverScope: "primary"` consults only the primary, so its claim
583
- * is `"lsp"` alone; an all-scope check adds each auxiliary server by id, which
584
- * is the same vocabulary `retagAuxiliaryDiagnostics` tags their findings with.
585
- *
586
- * A server named in `unconfirmedServerIds` is dropped: it produced no evidence
587
- * for this content, so claiming coverage for it would be the #1470/#1493 lie one
588
- * layer up. (Today an aux gap also demotes the whole verdict to "unconfirmed",
589
- * so the hook does not fire at all — this stays correct if that ever narrows.)
590
- */
591
- function coveredSourcesForCheck(file, serverScope, unconfirmedServerIds) {
592
- const unconfirmed = new Set(unconfirmedServerIds);
593
- const covered = new Set();
594
- let servers = [];
595
- try {
596
- servers = (getServersForFileWithConfig(file) ?? []);
597
- }
598
- catch {
599
- // A registry we cannot read is not a coverage claim. Returning an empty
600
- // set makes every retire fail closed, which is the safe direction for a
601
- // commit gate.
602
- return [];
603
- }
604
- for (const server of servers) {
605
- const auxiliary = server.role === "auxiliary";
606
- if (auxiliary && serverScope === "primary")
607
- continue;
608
- if (unconfirmed.has(server.id))
609
- continue;
610
- // The dispatch runner tags the primary language server's findings `lsp`;
611
- // auxiliaries keep their own tool id.
612
- covered.add(auxiliary ? server.id : "lsp");
613
- }
614
- return [...covered];
615
- }
616
- /**
617
- * #1645 review F3: `lsp_diagnostics` writes into the SAME widget store as
618
- * `lens_diagnostics mode=full`. Two tools writing one store must apply ONE rule
619
- * for "is this file's diagnostics demoted" — otherwise an orphan file blocks or
620
- * does not depending purely on which tool ran last, which is the #1633-V1
621
- * lesson. Every path in this file that reaches `reconcileWidgetFromLspResult`
622
- * or the rendered output routes its raw diagnostics through here first, so the
623
- * store, the counts, and the text all agree.
624
- *
625
- * Applied AFTER the confirmation verdict is computed, never before: confirmation
626
- * asks "did the server answer for this content", which the demotion must not
627
- * influence.
628
- */
629
- function demoteInferredForFile(file, diagnostics, cwd, lspService) {
630
- return demoteInferredProjectDiagnostics(diagnostics, {
631
- filePath: file,
632
- cwd,
633
- service: lspService,
634
- });
635
- }
636
- /**
637
- * #3088: the probe lane's stored-disposition / rule-policy / inline-suppression
638
- * gate — the same `clients/dispatch/finding-policy.ts` stack `mode=full` and
639
- * the per-edit dispatcher apply, called once per file at the position
640
- * `demoteInferredForFile` already established: AFTER the confirmation verdict
641
- * (which asks "did the server answer for this content" and must not be
642
- * influenced by a policy drop) and BEFORE the rendered output, the severity
643
- * filter and `reconcileWidgetFromLspResult`. One filtered set for all three, so
644
- * the text, the counts and the widget footer cannot disagree — and so the
645
- * footer reconcile can no longer re-arm a finding the mark-time
646
- * `reconcileWidgetDisposition` demoted.
647
- *
648
- * Fails OPEN: a filter that throws returns the unfiltered set plus one bounded
649
- * degradation record. A finding that stays visible is recoverable; one silently
650
- * hidden by a broken filter is the harm this lane exists to prevent
651
- * (AGENTS.md shape 48).
652
- */
653
- function applyProbeFindingPolicy(file, diagnostics, cwd, content,
654
- /**
655
- * Round 2 F1: the caller's severity threshold. The count reported to the
656
- * agent must be scoped to the SAME threshold the rendered result is, or a
657
- * `severity: "error"` probe of a repo carrying warning-level marks prints
658
- * "suppressed by disposition: N … Not a clean verdict" on a result that IS
659
- * clean at that threshold — the skill's own folder-check recipe would emit
660
- * the banner on every check. The threshold is applied HERE, in the tool that
661
- * owns both the render and the record, rather than in the three call sites
662
- * (three copies of one subtraction) or in
663
- * `clients/dispatch/finding-policy.ts`, which must stay threshold-free: its
664
- * other caller (`mode=full`) has no severity axis at all.
665
- */
666
- severity) {
667
- const started = Date.now();
668
- try {
669
- const result = applyLspFindingPolicy(diagnostics, {
670
- cwd,
671
- filePath: file,
672
- content,
673
- policyMap: loadProjectRulePolicyMap(cwd),
674
- fileRole: detectFileRole(file, content),
675
- });
676
- const inScopeBefore = applySeverityFilter(diagnostics, severity).length;
677
- const suppressed = inScopeBefore - applySeverityFilter(result.kept, severity).length;
678
- if (suppressed > 0) {
679
- // One record per FILE that actually dropped something the caller would
680
- // otherwise have SEEN, never one per finding (AGENTS.md "bounded
681
- // observability"). `total` is the in-scope population for the same
682
- // reason the count is, so the record and the rendered line agree.
683
- //
684
- // #3158 round 2 F4: `retainedSuppressed` is the widget store's
685
- // SUCCESS-path number — how many suppressed rows the store is carrying
686
- // INTO this scan, written by the scans before it. Until this, retention
687
- // was observable only when its per-file cap truncated
688
- // (`widget-suppressed-retention-capped`), so a healthy footer chip had no
689
- // record behind it at all. Folded into the record this lane already emits
690
- // rather than added as a second one: same cardinality (one per filtered
691
- // file per scan, never one per row), no new sink, and the two numbers are
692
- // read together — `suppressed` is what THIS scan dropped,
693
- // `retainedSuppressed` is what the footer chip is still counting.
694
- logLatency({
695
- type: "phase",
696
- toolName: "lsp_diagnostics",
697
- filePath: file,
698
- phase: "lsp_probe_disposition_filter",
699
- durationMs: Date.now() - started,
700
- metadata: {
701
- suppressed,
702
- total: inScopeBefore,
703
- retainedSuppressed: countRetainedSuppressedRows(file),
704
- },
705
- });
706
- }
707
- return { kept: result.kept, inlineKept: result.inlineKept, suppressed };
708
- }
709
- catch (err) {
710
- recordDegradationOnce({
711
- kind: "lsp-probe-finding-policy",
712
- subject: cwd,
713
- reason: err instanceof Error ? err.message : String(err),
714
- });
715
- return { kept: diagnostics, inlineKept: diagnostics, suppressed: 0 };
716
- }
717
- }
718
- /**
719
- * #3088 AC5/AC7: the content a cache REPLAY needs to evaluate STRICT
720
- * (`false-positive`) disposition anchors, which hash the finding's own line.
721
- * A cache hit means the file is unchanged since the entry was recorded, so this
722
- * is the same content the recording touch read — but it is a disk read the
723
- * replay path exists to avoid, so it is paid ONLY when the store actually holds
724
- * a strict mark. With no marks (the overwhelmingly common case) the probe path
725
- * adds zero I/O and the weak-anchored marks apply without content at all.
726
- */
727
- function replayContentForStrictMarks(file, cwd) {
728
- if (!hasStrictDispositionMarks(cwd))
729
- return undefined;
730
- try {
731
- return fs.readFileSync(file, "utf-8");
732
- }
733
- catch {
734
- // Fail open — an unreadable file degrades to the weak-anchored filter
735
- // rather than hiding or dropping anything.
736
- return undefined;
737
- }
738
- }
739
- function reconcileWidgetFromLspResult(file, rawDiags, confirmation, writeIndex, cwd, content,
740
- // #1095: true when the result's content binding demonstrably mismatches disk
741
- // (boundToCurrentDisk === false). Such a result — even a NON-EMPTY one, which
742
- // the pre-#1095 "non-empty is definitionally confirmed" doctrine would have
743
- // written straight through — must NOT re-cement the footer with a stale view
744
- // (#1092's window-1 transcript: 17 live-looking diagnostics while tsc exits
745
- // 0). "unknown"/true bindings leave the doctrine unchanged (fallback preserved
746
- // for servers that never bind a version).
747
- boundMismatch = false,
748
- // #1093: when these `rawDiags` were actually OBSERVED. Fresh touches observe
749
- // now (`undefined` → `Date.now()`); a cache HIT replays diagnostics scanned
750
- // earlier, so its caller passes the cache entry's `scannedAt` here so the
751
- // footer's `touchedAt` isn't re-armed to now() and the mtime-staleness gate
752
- // stays live (the #1092 re-arming defect).
753
- observedAt) {
754
- const confirmed = (rawDiags.length > 0 || confirmation !== "unconfirmed") && !boundMismatch;
755
- if (!confirmed)
756
- return { confirmed: false, blocking: true };
757
- try {
758
- // #692: provenance label ONLY — must never affect `rule`/identity (see
759
- // `ConvertLspDiagnosticsOptions.scanOrigin`'s doc comment).
760
- const diagnostics = convertLspDiagnostics(rawDiags, file, {
761
- scanOrigin: "lsp_diagnostics",
762
- });
763
- const retagged = retagAuxiliaryDiagnostics(diagnostics, rawDiags, content ?? "", { cwd, fileRole: detectFileRole(file, content) });
764
- const reconciled = reconcileScanDiagnostics(file, retagged, true, writeIndex, observedAt);
765
- if (!reconciled)
766
- return { confirmed: false, blocking: true };
767
- // #1561: the blocking tally comes from the SAME `isBlocking` predicate the
768
- // footer counts with — no second severity rule for the blocker-retire
769
- // decision to drift away from.
770
- return { confirmed: true, blocking: retagged.some(isBlocking) };
771
- }
772
- catch {
773
- // Never let a footer-reconciliation hiccup fail the diagnostics check.
774
- // A verdict we could not compute is NOT evidence of clean: report it as
775
- // still-blocking so no caller retires a blocker off a failed reconcile.
776
- return { confirmed: false, blocking: true };
777
- }
778
- }
779
- async function collectFileDiagnosticResult(file, severity, lspService, waitMs, nextWriteIndex, serverScope = "all",
780
- // #671: shared workspace-diagnostics cache (see `createWorkspaceDiagnostics
781
- // CacheContext`'s doc) — optional so single-file callers of this function
782
- // (there are none today, but keep it non-breaking) can omit it and simply
783
- // always touch. Only `collectBatchDiagnostics` (the batch/directory sweep)
784
- // passes these.
785
- cacheCtx, scopeKey,
786
- // #692: threaded through so `reconcileWidgetFromLspResult` can compute
787
- // `allowBlocking(cwd)` for a scan-reconciled aux finding — defaults to
788
- // `process.cwd()` for any call site that predates this (there are none
789
- // today besides the two below, both of which now pass it explicitly).
790
- cwd = process.cwd(),
791
- // #1561: see `createLspDiagnosticsTool`'s parameter doc. Called only for a
792
- // FRESH observation — never on the cache-hit replay below, whose `rawDiags`
793
- // are an OLD observation (#1093) and therefore no evidence about now.
794
- onConfirmedNoBlockers) {
795
- // Reserve the ordering token when this diagnostic operation starts, not when
796
- // its LSP promise settles. A slower old result must not receive a newer token
797
- // merely because it completed later (#1198).
798
- const writeIndex = nextWriteIndex?.();
799
- let stat;
800
- try {
801
- stat = fs.statSync(file);
802
- if (!stat.isFile()) {
803
- return { file, diagnostics: [], error: `${file}: not a file` };
804
- }
805
- }
806
- catch {
807
- return { file, diagnostics: [], error: `${file}: path not found` };
808
- }
809
- if (cacheCtx && scopeKey !== undefined) {
810
- const cached = cacheCtx.lookup(file, scopeKey);
811
- // #1095: a cached entry whose content binding demonstrably mismatches disk
812
- // (bytes changed without the mtime bump the freshness gate would catch) is
813
- // NOT served — fall through to a fresh touch instead of replaying a stale
814
- // cached result. "unknown"/true bindings serve as before.
815
- if (cached && cached.binding.boundToCurrentDisk !== false) {
816
- const confirmation = cached.diagnostics.length === 0 ? "clean" : undefined;
817
- // #1645 review F3: a cache REPLAY writes the widget store exactly like a
818
- // fresh touch does, so it gets the same demotion. Without this, replaying
819
- // yesterday's cached blocker would re-cement an orphan file as blocking
820
- // after mode=full had demoted it.
821
- const demotedCached = await demoteInferredForFile(file, cached.diagnostics, cwd, lspService);
822
- // #3088 AC5: a replay is served to the agent exactly like a fresh
823
- // observation, so it passes the same filter. The cached set is already
824
- // inline-suppression-clean (the record below stores `inlineKept`), so
825
- // only the revocable store/config filters run here.
826
- const cachedPolicy = applyProbeFindingPolicy(file, demotedCached, cwd, replayContentForStrictMarks(file, cwd), severity);
827
- const cachedDiags = cachedPolicy.kept;
828
- const filteredDiags = applySeverityFilter(cachedDiags, severity);
829
- // #692: cached.diagnostics were already suppression-/skipTestFiles-
830
- // filtered at write time (this same code path); no file content was
831
- // cached alongside them, so `undefined` here is a safe re-check, not
832
- // a gap.
833
- // #1093: this is a CACHE HIT — a replay of an OLD observation. Stamp the
834
- // footer's `touchedAt` with the cache entry's original `scannedAt`, NOT
835
- // now(), or a repeat check that only re-serves the cache would keep
836
- // re-arming the mtime-staleness gate and a resolved finding would render
837
- // forever (the #1092 defect).
838
- reconcileWidgetFromLspResult(file, cachedDiags, confirmation, writeIndex, cwd, undefined,
839
- // This branch only runs when the cache binding is not a mismatch
840
- // (guarded above), so boundMismatch is false; #1093's observedAt is
841
- // the cache entry's original scan time.
842
- false, cached.scannedAt);
843
- return {
844
- file,
845
- diagnostics: diagnosticsToFileDiags(file, filteredDiags),
846
- confirmation,
847
- primaryServerId: primaryServerId(file),
848
- ...(cachedPolicy.suppressed > 0 && {
849
- dispositionSuppressed: cachedPolicy.suppressed,
850
- }),
851
- };
852
- }
853
- }
854
- const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, diagnosticsUnsupportedServerIds, content: collectedContent, binding, tooLargeReason, skipReason, } = await collectDiagnosticsForFile(file, lspService, cwd, waitMs, serverScope);
855
- if (tooLargeReason !== undefined) {
856
- return { file, diagnostics: [], outcome: "too_large", tooLargeReason };
857
- }
858
- const health = lspService.getDiagnosticsHealth?.(file);
859
- // #570: a timed-out priming check is never a confirmed "clean" — treat it
860
- // as unconfirmed without consulting the (unrelated) silent-tier
861
- // classifier, and remember why so the rendered text is accurate.
862
- // #611: a genuinely empty (not just severity-filtered-away) push-based
863
- // result gets a shot at the tier-3 sync escape hatch before "unconfirmed"
864
- // — it may surface real diagnostics the server never published, which must
865
- // be merged in rather than discarded.
866
- let effectiveRawDiags = rawDiags;
867
- let confirmation;
868
- if (diagnosticsUnsupportedServerIds.length > 0) {
869
- // No diagnostic provider and no push evidence is a capability boundary,
870
- // not a clean result and not a timeout.
871
- confirmation = undefined;
872
- }
873
- else if (skipReason !== undefined) {
874
- confirmation = "unconfirmed";
875
- }
876
- else if (timedOut) {
877
- if (applySeverityFilter(rawDiags, severity).length === 0) {
878
- confirmation = "unconfirmed";
879
- }
880
- }
881
- else if (canTrustTouchConfirmation(file, serverScope, confirmedByTouch)) {
882
- if (applySeverityFilter(rawDiags, severity).length === 0) {
883
- confirmation = "clean";
884
- }
885
- }
886
- else if (rawDiags.length === 0) {
887
- const resolved = await resolveEmptyResult(file, lspService);
888
- effectiveRawDiags = resolved.diagnostics;
889
- confirmation = resolved.confirmed
890
- ? resolved.diagnostics.length === 0
891
- ? "clean"
892
- : undefined
893
- : "unconfirmed";
894
- }
895
- else if (applySeverityFilter(rawDiags, severity).length === 0) {
896
- confirmation = await classifyEmptyResult(file, lspService);
897
- }
898
- // #1095: a result whose content binding demonstrably mismatches disk is
899
- // demoted to "unconfirmed" — it must neither confirm the footer nor be cached
900
- // as clean, regardless of how many diagnostics it carries (the #1092
901
- // re-cementing path). "unknown"/true bindings leave the verdict untouched.
902
- const boundMismatch = binding?.boundToCurrentDisk === false;
903
- if (boundMismatch)
904
- confirmation = "unconfirmed";
905
- // #1470/#1493: an auxiliary that never reported — cut off by the aux grace timer,
906
- // or silent with nothing published for this content — contributed no evidence
907
- // about this file, so a "clean" verdict computed from the merged result would
908
- // be claiming coverage this batch does not have. Demote it — that also keeps
909
- // the entry out of the workspace cache below, which would otherwise replay the
910
- // partial answer as a confirmed clean on every later sweep.
911
- if (unconfirmedServerIds.length > 0 && confirmation === "clean") {
912
- confirmation = "unconfirmed";
913
- }
914
- // #1645 review F3: one demotion rule for every writer of the widget store.
915
- effectiveRawDiags = await demoteInferredForFile(file, effectiveRawDiags, cwd, lspService);
916
- // #3088: one filter for the output, the counts and the footer reconcile.
917
- const policy = applyProbeFindingPolicy(file, effectiveRawDiags, cwd, collectedContent, severity);
918
- effectiveRawDiags = policy.kept;
919
- const filteredDiags = applySeverityFilter(effectiveRawDiags, severity);
920
- const verdict = reconcileWidgetFromLspResult(file, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
921
- if (verdict.confirmed && !verdict.blocking) {
922
- onConfirmedNoBlockers?.({
923
- filePath: file,
924
- writeIndex,
925
- coveredSources: coveredSourcesForCheck(file, serverScope, unconfirmedServerIds),
926
- cwd,
927
- });
928
- }
929
- // #671: only a CONFIRMED outcome ("clean", or a non-empty result — either
930
- // is definitionally confirmed per this function's own doctrine above) is
931
- // safe to cache; "unconfirmed" (timeout OR a silent-tier server's
932
- // unescapable empty push) must never be persisted as a cacheable clean
933
- // result — same false-clean bug class `runWorkspaceDiagnostics`'s cache
934
- // wiring guards against. #1095: the entry carries the content fingerprint so a
935
- // later lookup can verify it against disk beyond the mtime proxy.
936
- if (cacheCtx &&
937
- scopeKey !== undefined &&
938
- confirmation !== "unconfirmed" &&
939
- diagnosticsUnsupportedServerIds.length === 0 &&
940
- unconfirmedServerIds.length === 0) {
941
- // #3088: the entry records the INLINE-suppressed set, never the
942
- // disposition/rule-policy-filtered one. An inline `pi-lens-ignore` comment
943
- // cannot change without invalidating this content-keyed entry, so baking it
944
- // in is safe and makes every later replay consistent with a fresh probe; a
945
- // disposition mark or a `.pi-lens.json` rule can be revoked at any moment,
946
- // so caching THEIR effect would keep a finding hidden after its mark was
947
- // removed. The replay branch above re-applies those two on every serve.
948
- cacheCtx.record(file, scopeKey, policy.inlineKept, stat.mtimeMs, collectedContent !== undefined
949
- ? hashDiagnosticContent(collectedContent)
950
- : undefined, stat.size);
951
- }
952
- return {
953
- file,
954
- diagnostics: diagnosticsToFileDiags(file, filteredDiags),
955
- unavailable: lspUnavailableMessage(file, health),
956
- confirmation,
957
- timedOut: confirmation === "unconfirmed" ? timedOut : undefined,
958
- ...(skipReason !== undefined && { skipReason }),
959
- primaryServerId: primaryServerId(file),
960
- diagnosticsUnsupported: diagnosticsUnsupportedServerIds.length > 0,
961
- ...(policy.suppressed > 0 && {
962
- dispositionSuppressed: policy.suppressed,
963
- }),
964
- };
965
- }
966
- async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd(),
967
- // #1561: see `createLspDiagnosticsTool`'s parameter doc. This is the path the
968
- // live incident took (`mode: "file"`).
969
- onConfirmedNoBlockers) {
970
- // Reserve the token before awaiting this file's LSP result. The direct-file
971
- // path performs its own confirmation/reconciliation below (#1198).
972
- const writeIndex = nextWriteIndex?.();
973
- const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, diagnosticsUnsupportedServerIds, content: collectedContent, binding, tooLargeReason, skipReason, } = await collectDiagnosticsForFile(absPath, lspService, cwd, waitMs, serverScope);
974
- if (tooLargeReason !== undefined) {
975
- return {
976
- content: [{ type: "text", text: tooLargeReason }],
977
- details: {
978
- filePath: absPath,
979
- mode: "file",
980
- severity,
981
- serverScope,
982
- outcome: "too_large",
983
- tooLargeReason,
984
- diagnostics: [],
985
- totalDiagnostics: 0,
986
- },
987
- };
988
- }
989
- const lspHealth = lspService.getDiagnosticsHealth?.(absPath);
990
- const unavailable = lspUnavailableMessage(absPath, lspHealth);
991
- // #533: an empty result needs a confirmed/unconfirmed verdict — a push-only,
992
- // silent-on-clean server (classic typescript) publishes nothing on a
993
- // clean→clean edit, so "0 diagnostics" from it is unverifiable, not clean.
994
- // #570: a timed-out priming check is a second, distinct reason a result
995
- // can be unconfirmed — checked first since it's a property of THIS check,
996
- // not a general server-capability classification.
997
- // #611: a genuinely empty (not just severity-filtered-away) result gets a
998
- // shot at the tier-3 sync escape hatch before "unconfirmed" — real
999
- // diagnostics it surfaces are merged in, not discarded.
1000
- let effectiveRawDiags = rawDiags;
1001
- let confirmation;
1002
- if (diagnosticsUnsupportedServerIds.length > 0) {
1003
- confirmation = undefined;
1004
- }
1005
- else if (skipReason !== undefined) {
1006
- confirmation = "unconfirmed";
1007
- }
1008
- else if (timedOut) {
1009
- if (applySeverityFilter(rawDiags, severity).length === 0) {
1010
- confirmation = "unconfirmed";
1011
- }
1012
- }
1013
- else if (canTrustTouchConfirmation(absPath, serverScope, confirmedByTouch)) {
1014
- if (applySeverityFilter(rawDiags, severity).length === 0) {
1015
- confirmation = "clean";
1016
- }
1017
- }
1018
- else if (rawDiags.length === 0) {
1019
- const resolved = await resolveEmptyResult(absPath, lspService);
1020
- effectiveRawDiags = resolved.diagnostics;
1021
- confirmation = resolved.confirmed
1022
- ? resolved.diagnostics.length === 0
1023
- ? "clean"
1024
- : undefined
1025
- : "unconfirmed";
1026
- }
1027
- else if (applySeverityFilter(rawDiags, severity).length === 0) {
1028
- confirmation = await classifyEmptyResult(absPath, lspService);
1029
- }
1030
- // #1095: demote a result whose content binding mismatches disk to
1031
- // "unconfirmed" (the #1092 re-cementing path) — a non-empty stale result is no
1032
- // longer "definitionally confirmed". "unknown"/true bindings are unchanged.
1033
- const boundMismatch = binding?.boundToCurrentDisk === false;
1034
- if (boundMismatch)
1035
- confirmation = "unconfirmed";
1036
- // #1470/#1493: NARROWED, not collapsed. An auxiliary that never reported — the aux
1037
- // grace timer cut it off, or it stayed silent with nothing published for this
1038
- // content — makes the FILE-level verdict unconfirmed. The merged result is missing
1039
- // whatever that scanner would have said, and this tool is the security lane's read surface. The
1040
- // PRIMARY's own verdict is untouched (`primaryCoverageGapOnly` below), so a
1041
- // TypeScript answer stays "confirmed clean" on its own line while an explicit
1042
- // line names the scanner whose coverage is absent.
1043
- const primaryCoverageGapOnly = unconfirmedServerIds.length > 0 && confirmation === "clean";
1044
- if (primaryCoverageGapOnly)
1045
- confirmation = "unconfirmed";
1046
- // #1645 review F3: one demotion rule for every writer of the widget store.
1047
- effectiveRawDiags = await demoteInferredForFile(absPath, effectiveRawDiags, cwd, lspService);
1048
- // #3088: one filter for the output, the counts and the footer reconcile.
1049
- const policy = applyProbeFindingPolicy(absPath, effectiveRawDiags, cwd, collectedContent, severity);
1050
- effectiveRawDiags = policy.kept;
1051
- const filtered = applySeverityFilter(effectiveRawDiags, severity);
1052
- const total = filtered.length;
1053
- const truncated = total > MAX_DIAGNOSTICS;
1054
- const limited = truncated ? filtered.slice(0, MAX_DIAGNOSTICS) : filtered;
1055
- const unconfirmed = confirmation === "unconfirmed";
1056
- const verdict = reconcileWidgetFromLspResult(absPath, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
1057
- // #1561: a confirmed current view with nothing at the blocking tier retires
1058
- // this file's stale inline blocker — the store #571 corrected the footer for
1059
- // but never reached, which is how a resolved cross-file finding kept being
1060
- // injected as "Unresolved from this turn" for the rest of the session.
1061
- if (verdict.confirmed && !verdict.blocking) {
1062
- onConfirmedNoBlockers?.({
1063
- filePath: absPath,
1064
- writeIndex,
1065
- coveredSources: coveredSourcesForCheck(absPath, serverScope, unconfirmedServerIds),
1066
- cwd,
1067
- });
1068
- }
1069
- const primaryId = primaryServerId(absPath);
1070
- const primaryDiags = limited.filter((d) => d.serverId === primaryId);
1071
- const auxiliaryDiags = limited.filter((d) => d.serverId !== primaryId);
1072
- // Primary confirmation is always its own line, independent of how many
1073
- // auxiliary findings exist — a wall of ast-grep/opengrep noise must never
1074
- // bury whether the actual language server confirmed the file clean.
1075
- const primaryLine = (() => {
1076
- if (diagnosticsUnsupportedServerIds.length > 0) {
1077
- return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: navigation-only — diagnostics unsupported (no pull provider or publish evidence).`;
1078
- }
1079
- if (timedOut) {
1080
- return ("Primary LSP: check timed out — NOT the same as 0 diagnostics; the " +
1081
- "file may still have errors that just hadn't been reported yet. " +
1082
- "Re-check after the server settles, or increase waitMs.");
1083
- }
1084
- // #1470: a file demoted ONLY because an auxiliary was cut off must not render
1085
- // the silent-on-clean text — the primary did confirm, and saying otherwise is
1086
- // the same overclaim in the opposite direction. The coverage line below names
1087
- // what is actually missing.
1088
- if (unconfirmed && !primaryCoverageGapOnly) {
1089
- return (`Primary LSP${primaryId ? ` (${primaryId})` : ""}: unconfirmed — ` +
1090
- "cannot confirm clean (push-only, silent-on-clean, e.g. classic " +
1091
- "typescript-language-server never publishes on a clean re-check). " +
1092
- "NOT the same as 0 diagnostics; re-check after an edit, or use " +
1093
- "waitMs to wait longer.");
1094
- }
1095
- if (primaryDiags.length === 0) {
1096
- return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: confirmed clean.`;
1097
- }
1098
- return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: ${primaryDiags.length} diagnostic${primaryDiags.length === 1 ? "" : "s"}.`;
1099
- })();
1100
- // #1470: this is the narrowing made readable. It states exactly which servers
1101
- // this result does NOT speak for, so "no auxiliary findings" can never be read
1102
- // as "the security scanners found nothing".
1103
- const coverageLine = unconfirmedServerIds.length > 0
1104
- ? `Auxiliary coverage INCOMPLETE — ${[...unconfirmedServerIds].join(", ")} did not answer within the wait budget, so ${unconfirmedServerIds.length === 1 ? "its findings are" : "their findings are"} NOT included here. This is not a clean bill of health for ${unconfirmedServerIds.length === 1 ? "that scanner" : "those scanners"}; re-check after the next edit. waitMs can extend an ordinary wait, but it cannot override a session-demoted scanner.`
1105
- : undefined;
1106
- // #3088: the #1616 suppressed-bucket rule on this lane — a policy drop is
1107
- // stated as a count, never left to read as "nothing was wrong here"
1108
- // (AGENTS.md shape 10). Bounded: one line per call, whatever the count.
1109
- const suppressedLine = dispositionSuppressedLine(policy.suppressed);
1110
- let text;
1111
- if (total === 0) {
1112
- text = [
1113
- primaryLine,
1114
- "",
1115
- unavailable ?? "No auxiliary findings.",
1116
- ...(coverageLine ? [coverageLine] : []),
1117
- ...(suppressedLine ? [suppressedLine] : []),
1118
- ].join("\n");
1119
- }
1120
- else {
1121
- const lines = [primaryLine, ""];
1122
- if (primaryDiags.length > 0) {
1123
- lines.push(...primaryDiags.map(formatDiag), "");
1124
- }
1125
- if (auxiliaryDiags.length > 0) {
1126
- lines.push(`Auxiliary findings (${auxiliaryDiags.length}):`);
1127
- lines.push(...auxiliaryDiags.map(formatDiag));
1128
- }
1129
- if (coverageLine)
1130
- lines.push("", coverageLine);
1131
- if (suppressedLine)
1132
- lines.push("", suppressedLine);
1133
- if (unavailable)
1134
- lines.unshift(unavailable, "");
1135
- if (truncated) {
1136
- lines.unshift(`Found ${total} diagnostics (showing first ${MAX_DIAGNOSTICS}):`);
1137
- }
1138
- text = lines.join("\n");
1139
- }
1140
- return {
1141
- content: [{ type: "text", text }],
1142
- details: {
1143
- filePath: absPath,
1144
- mode: "file",
1145
- severity,
1146
- serverScope,
1147
- ...(unavailable ? { unavailable } : {}),
1148
- primaryServerId: primaryId,
1149
- primaryDiagnosticsCount: primaryDiags.length,
1150
- auxiliaryDiagnosticsCount: auxiliaryDiags.length,
1151
- diagnostics: limited.map((d) => ({
1152
- line: d.range?.start?.line,
1153
- character: d.range?.start?.character,
1154
- severity: d.severity,
1155
- message: d.message,
1156
- source: d.source,
1157
- code: d.code,
1158
- })),
1159
- totalDiagnostics: total,
1160
- ...(policy.suppressed > 0 && {
1161
- dispositionSuppressed: policy.suppressed,
1162
- }),
1163
- truncated,
1164
- unconfirmed,
1165
- timedOut: unconfirmed ? timedOut : undefined,
1166
- navigationOnlyFiles: diagnosticsUnsupportedServerIds.length > 0 ? 1 : undefined,
1167
- ...(skipReason !== undefined && { skipReason }),
1168
- // #1470: which servers this result does NOT speak for. Absent when it
1169
- // speaks for all of them.
1170
- ...(unconfirmedServerIds.length > 0 && {
1171
- unconfirmedServerIds: [...unconfirmedServerIds],
1172
- }),
1173
- lspHealth,
1174
- waitMs,
1175
- },
1176
- };
1177
- }
1178
- /**
1179
- * #533: tally the per-file discriminated outcome across a batch/directory
1180
- * result set. `unconfirmed` files are those whose diagnostics collapsed to an
1181
- * empty array from a push-only, silent-on-clean server (see
1182
- * `classifyEmptyResult`) — they must never be folded into "clean" in the
1183
- * aggregate render, or a majority-unconfirmed result reads as a false "0
1184
- * diagnostics across N files".
1185
- */
1186
- function tallyConfirmation(results) {
1187
- let clean = 0;
1188
- let unconfirmed = 0;
1189
- let timedOut = 0;
1190
- let navigationOnly = 0;
1191
- let tooLarge = 0;
1192
- for (const result of results) {
1193
- if (result.tooLargeReason) {
1194
- tooLarge += 1;
1195
- continue;
1196
- }
1197
- if (result.diagnosticsUnsupported) {
1198
- navigationOnly += 1;
1199
- continue;
1200
- }
1201
- if (result.diagnostics.length > 0)
1202
- continue;
1203
- if (result.confirmation === "unconfirmed") {
1204
- unconfirmed += 1;
1205
- // #570: timed-out checks are a subset of "unconfirmed" — tallied
1206
- // separately so the aggregate text can say WHY, not just THAT.
1207
- if (result.timedOut)
1208
- timedOut += 1;
1209
- }
1210
- else {
1211
- clean += 1;
1212
- }
1213
- }
1214
- return { clean, unconfirmed, timedOut, navigationOnly, tooLarge };
1215
- }
1216
- function classifyBatchFileOutcome(result) {
1217
- if (result.error)
1218
- return "failed";
1219
- if (result.tooLargeReason)
1220
- return "too_large";
1221
- if (result.diagnosticsUnsupported)
1222
- return "unsupported";
1223
- // A timed-out/unconfirmed answer may contain partial findings, but it cannot
1224
- // honestly be called a complete findings result. Keep the raw findings for
1225
- // investigation while making the aggregate incomplete.
1226
- if (result.timedOut || result.confirmation === "unconfirmed") {
1227
- return "inconclusive";
1228
- }
1229
- if (result.diagnostics.length > 0)
1230
- return "findings";
1231
- if (result.unavailable) {
1232
- return result.primaryServerId ? "unavailable" : "unsupported";
1233
- }
1234
- if (!result.primaryServerId)
1235
- return "unsupported";
1236
- return "clean";
1237
- }
1238
- function inconclusiveBatchResult(file, reason) {
1239
- return {
1240
- file,
1241
- diagnostics: [],
1242
- confirmation: "unconfirmed",
1243
- timedOut: true,
1244
- outcome: "inconclusive",
1245
- inconclusiveReason: reason,
1246
- };
1247
- }
1248
- /**
1249
- * #570: build the explanatory clause for a batch/directory result that has
1250
- * unconfirmed files, distinguishing timed-out checks from the pre-existing
1251
- * #533 silent-on-clean-server bucket — both are "unconfirmed" for counting,
1252
- * but the reason differs and misreporting a timeout as "server can't confirm
1253
- * clean" would itself be misleading.
1254
- */
1255
- function unconfirmedReasonClause(unconfirmed, timedOut) {
1256
- const silent = unconfirmed - timedOut;
1257
- if (timedOut > 0 && silent > 0) {
1258
- return (`${timedOut} timed out (check didn't complete within budget) and ` +
1259
- `${silent} from a server that cannot confirm clean (push-only, ` +
1260
- "silent-on-clean).");
1261
- }
1262
- if (timedOut > 0) {
1263
- return `${timedOut} timed out (check didn't complete within the wait budget).`;
1264
- }
1265
- return ("from a server that cannot confirm clean (push-only, silent-on-clean; " +
1266
- "e.g. classic typescript-language-server does not publish on a clean " +
1267
- "re-check).");
1268
- }
1269
- /**
1270
- * Fan out `collectFileDiagnosticResult` across a file list at bounded
1271
- * concurrency and reduce the results into the shape both batch-style callers
1272
- * (`runBatchFileDiagnostics`/`runDirectoryDiagnostics`) render from —
1273
- * previously duplicated identically between them (SonarCloud
1274
- * `new_duplicated_lines_density` gate, surfaced when #571 added the
1275
- * `nextWriteIndex` threading to both call sites). Purely mechanical
1276
- * extraction: no behavior change, and does NOT touch the confirmed/
1277
- * unconfirmed semantics `collectFileDiagnosticResult`/`tallyConfirmation`
1278
- * already encode — those, and `lens_diagnostics` mode=full's separate,
1279
- * deliberately different confirmation gate in `tools/lens-diagnostics.ts`,
1280
- * are unrelated to this file's internal duplication and are left exactly
1281
- * as they were.
1282
- */
1283
- async function collectBatchDiagnostics(files, severity, lspService, options) {
1284
- // #671: one cache context for this whole batch/directory sweep — loaded
1285
- // once, written back once after every file has been processed (see the
1286
- // `persist()` call below), rather than round-tripping the on-disk cache
1287
- // file per-file. Shared store with `runWorkspaceDiagnostics` (`lens_
1288
- // diagnostics mode=full`'s engine); `scopeKey` keeps the two tools'
1289
- // differently-scoped touches (this tool never excludes any server, that
1290
- // one excludes opengrep — see `buildScopeKey`'s doc) from cross-serving
1291
- // entries that wouldn't actually match what each asked for.
1292
- const resolvedCwd = options.cwd ?? process.cwd();
1293
- const cacheCtx = createWorkspaceDiagnosticsCacheContext(resolvedCwd);
1294
- const scopeKey = buildScopeKey(options.serverScope ?? "all");
1295
- const resultsByIndex = new Map();
1296
- let completed = 0;
1297
- const pendingIndices = new Map();
1298
- files.forEach((file, index) => {
1299
- const queue = pendingIndices.get(file);
1300
- if (queue)
1301
- queue.push(index);
1302
- else
1303
- pendingIndices.set(file, [index]);
1304
- });
1305
- const groups = groupFilesByPrimaryServer(files);
1306
- await runPerServerGroups(groups, options.concurrency, async (group) => {
1307
- if (options.signal?.aborted)
1308
- return;
1309
- const first = group.files[0];
1310
- if (first &&
1311
- lspService &&
1312
- !isWarmAttached() &&
1313
- typeof lspService.ensureWarmForSweep === "function") {
1314
- await lspService.ensureWarmForSweep(first, {
1315
- signal: options.signal,
1316
- });
1317
- if (options.signal?.aborted)
1318
- return;
1319
- }
1320
- await mapWithConcurrency(group.files, 1, async (file) => {
1321
- // Keep duplicate explicit paths in their original result slots.
1322
- const index = pendingIndices.get(file).shift();
1323
- const work = collectFileDiagnosticResult(file, severity, lspService, options.waitMs, options.nextWriteIndex, options.serverScope, cacheCtx, scopeKey, resolvedCwd, options.onConfirmedNoBlockers);
1324
- const bounded = withDeadline(work, {
1325
- ms: batchFileDeadlineMs(),
1326
- onTimeout: "undefined",
1327
- onReject: "undefined",
1328
- });
1329
- const result = options.signal
1330
- ? await Promise.race([
1331
- bounded,
1332
- new Promise((resolve) => {
1333
- if (options.signal?.aborted) {
1334
- resolve(undefined);
1335
- return;
1336
- }
1337
- options.signal?.addEventListener("abort", () => resolve(undefined), {
1338
- once: true,
1339
- });
1340
- }),
1341
- ])
1342
- : await bounded;
1343
- resultsByIndex.set(index, result ??
1344
- inconclusiveBatchResult(file, options.signal?.aborted
1345
- ? "Batch aborted before this file completed."
1346
- : `File check exceeded ${batchFileDeadlineMs()}ms.`));
1347
- completed += 1;
1348
- options.onProgress?.(completed, files.length);
1349
- }, options.signal);
1350
- }, options.signal);
1351
- // The retired local pool returned only slots whose mapper had run. Keep that
1352
- // dense abort contract while restoring the original file order for callers.
1353
- const results = [...resultsByIndex.entries()]
1354
- .sort(([left], [right]) => left - right)
1355
- .map(([, result]) => result);
1356
- // Persist whatever was recorded, including a partial/aborted sweep's
1357
- // already-completed files — same "don't throw away confirmed work"
1358
- // posture as `runWorkspaceDiagnostics`.
1359
- cacheCtx.persist();
1360
- const fileErrors = results.flatMap((result) => result.error ? [result.error] : []);
1361
- const lspHealthWarnings = results.flatMap((result) => result.unavailable ? [result.unavailable] : []);
1362
- const allDiags = results.flatMap((result) => result.diagnostics);
1363
- const total = allDiags.length;
1364
- const truncated = total > MAX_DIAGNOSTICS;
1365
- const display = truncated ? allDiags.slice(0, MAX_DIAGNOSTICS) : allDiags;
1366
- const { clean, unconfirmed, timedOut } = tallyConfirmation(results);
1367
- for (const result of results) {
1368
- result.outcome = classifyBatchFileOutcome(result);
1369
- }
1370
- const outcomeCounts = Object.fromEntries([
1371
- "clean",
1372
- "findings",
1373
- "unsupported",
1374
- "unavailable",
1375
- "failed",
1376
- "too_large",
1377
- "inconclusive",
1378
- ].map((outcome) => [
1379
- outcome,
1380
- results.filter((result) => result.outcome === outcome).length,
1381
- ]));
1382
- // Per-file primary-server lookup so a flattened multi-file `display` list
1383
- // can still be split into "primary findings" vs "auxiliary findings" —
1384
- // `clean`/`unconfirmed` above already reflect ONLY the primary server's
1385
- // confirmation; this split does the same job for the listed diagnostics.
1386
- const primaryIdByFile = new Map(results.map((r) => [r.file, r.primaryServerId]));
1387
- const primaryDisplay = display.filter((d) => d.serverId === primaryIdByFile.get(d.file));
1388
- const auxiliaryDisplay = display.filter((d) => d.serverId !== primaryIdByFile.get(d.file));
1389
- return {
1390
- results,
1391
- fileErrors,
1392
- lspHealthWarnings,
1393
- total,
1394
- truncated,
1395
- display,
1396
- primaryDisplay,
1397
- auxiliaryDisplay,
1398
- clean,
1399
- unconfirmed,
1400
- timedOut,
1401
- outcomeCounts,
1402
- incompleteFiles: Math.max(0, files.length - results.length),
1403
- };
1404
- }
1405
- async function runBatchFileDiagnostics(absPaths, severity, lspService, options) {
1406
- if (absPaths.length === 0) {
1407
- return {
1408
- content: [{ type: "text", text: "No file paths provided." }],
1409
- isError: true,
1410
- details: { mode: "batch", severity, filesChecked: 0 },
1411
- };
1412
- }
1413
- const { results, fileErrors, lspHealthWarnings, total, truncated, display, primaryDisplay, auxiliaryDisplay, clean, unconfirmed, timedOut, outcomeCounts, incompleteFiles, } = await collectBatchDiagnostics(absPaths, severity, lspService, options);
1414
- const navigationOnly = results.filter((result) => result.diagnosticsUnsupported).length;
1415
- // #3088: the batch's own suppressed bucket — one summed line, never one per
1416
- // file or per finding.
1417
- const dispositionSuppressed = results.reduce((sum, result) => sum + (result.dispositionSuppressed ?? 0), 0);
1418
- const lines = [
1419
- `Files checked: ${results.length}`,
1420
- `Total diagnostics: ${total}`,
1421
- `Concurrency: ${options.concurrency}`,
1422
- ];
1423
- if (options.waitMs !== undefined)
1424
- lines.push(`Wait budget: ${options.waitMs}ms`);
1425
- lines.push(`Outcomes: ${Object.entries(outcomeCounts)
1426
- .map(([outcome, count]) => `${outcome}=${count}`)
1427
- .join(", ")}`);
1428
- const notConfirmed = outcomeCounts.inconclusive +
1429
- outcomeCounts.unavailable +
1430
- outcomeCounts.unsupported +
1431
- outcomeCounts.failed +
1432
- outcomeCounts.too_large +
1433
- incompleteFiles;
1434
- if (notConfirmed > 0) {
1435
- lines.push("", `Checks not confirmed: ${notConfirmed} (inconclusive/unavailable/unsupported/failed or not started).`);
1436
- }
1437
- if (incompleteFiles > 0) {
1438
- lines.push("", `Batch incomplete: ${incompleteFiles} file${incompleteFiles === 1 ? "" : "s"} were not confirmed because the batch was aborted.`);
1439
- }
1440
- if (fileErrors.length > 0)
1441
- lines.push("", "File errors:", ...fileErrors);
1442
- const outcomeDetails = results.map((result) => ({
1443
- file: result.file,
1444
- outcome: result.outcome,
1445
- reason: result.tooLargeReason ??
1446
- result.inconclusiveReason ??
1447
- result.error ??
1448
- result.unavailable,
1449
- }));
1450
- const tooLargeLines = renderBatchOutcomeLines(outcomeDetails);
1451
- if (tooLargeLines.length > 0) {
1452
- lines.push("", "Files too large for LSP diagnostics:", ...tooLargeLines);
1453
- }
1454
- if (lspHealthWarnings.length > 0) {
1455
- lines.push("", "LSP health warnings:", ...lspHealthWarnings.slice(0, 10));
1456
- }
1457
- // #533/#570: surface unconfirmed files regardless of whether OTHER files in
1458
- // the batch found real diagnostics — a mixed found/unconfirmed result must
1459
- // not let the unconfirmed files silently pass as clean just because the
1460
- // batch as a whole isn't "0 diagnostics". This tally is primary-server-only
1461
- // (see collectFileDiagnosticResult) — it's the batch-level equivalent of
1462
- // the single-file "Primary LSP: ..." line, always reported on its own.
1463
- if (unconfirmed > 0) {
1464
- lines.push("", `${clean} file${clean === 1 ? "" : "s"} confirmed clean, ${unconfirmed} unconfirmed: ` +
1465
- `${unconfirmedReasonClause(unconfirmed, timedOut)} NOT the same as 0 diagnostics.`);
1466
- }
1467
- if (display.length === 0) {
1468
- if (unconfirmed === 0 && outcomeCounts.clean === results.length) {
1469
- lines.push("", "No diagnostics found.");
1470
- }
1471
- }
1472
- else {
1473
- if (primaryDisplay.length > 0) {
1474
- lines.push("", `Primary findings (${primaryDisplay.length}):`);
1475
- lines.push(...primaryDisplay.map(formatDisplayDiag));
1476
- }
1477
- if (auxiliaryDisplay.length > 0) {
1478
- lines.push("", `Auxiliary findings (${auxiliaryDisplay.length}):`);
1479
- lines.push(...auxiliaryDisplay.map(formatDisplayDiag));
1480
- }
1481
- if (truncated) {
1482
- lines.push("", `... (${total - MAX_DIAGNOSTICS} more diagnostics not shown)`);
1483
- }
1484
- }
1485
- const suppressedLine = dispositionSuppressedLine(dispositionSuppressed);
1486
- if (suppressedLine)
1487
- lines.push("", suppressedLine);
1488
- return {
1489
- content: [{ type: "text", text: lines.join("\n") }],
1490
- details: {
1491
- mode: "batch",
1492
- severity,
1493
- serverScope: options.serverScope ?? "all",
1494
- filesChecked: results.length,
1495
- concurrency: options.concurrency,
1496
- waitMs: options.waitMs,
1497
- diagnostics: display,
1498
- primaryDiagnosticsCount: primaryDisplay.length,
1499
- auxiliaryDiagnosticsCount: auxiliaryDisplay.length,
1500
- totalDiagnostics: total,
1501
- ...(dispositionSuppressed > 0 && { dispositionSuppressed }),
1502
- truncated,
1503
- cleanFiles: clean,
1504
- unconfirmedFiles: unconfirmed,
1505
- navigationOnlyFiles: navigationOnly > 0 ? navigationOnly : undefined,
1506
- timedOutFiles: timedOut > 0 ? timedOut : undefined,
1507
- outcomes: results.map((result) => ({
1508
- file: result.file,
1509
- outcome: result.outcome,
1510
- reason: result.tooLargeReason ??
1511
- result.inconclusiveReason ??
1512
- result.error ??
1513
- result.unavailable,
1514
- primaryDiagnosticsCount: result.diagnostics.filter((diagnostic) => diagnostic.serverId === result.primaryServerId).length,
1515
- auxiliaryDiagnosticsCount: result.diagnostics.filter((diagnostic) => diagnostic.serverId !== result.primaryServerId).length,
1516
- })),
1517
- outcomeCounts,
1518
- incompleteFiles: incompleteFiles > 0 ? incompleteFiles : undefined,
1519
- fileErrors: fileErrors.length > 0 ? fileErrors : undefined,
1520
- lspHealthWarnings: lspHealthWarnings.length > 0 ? lspHealthWarnings : undefined,
1521
- },
1522
- };
1523
- }
1524
- /**
1525
- * The scan-language DECISION `runDirectoryDiagnostics` makes, pulled out as
1526
- * its own function so `tests/tools/lsp-diagnostics-scan-family.test.ts` can
1527
- * pin it against the golden `LANG_EXTENSIONS` table for every 1- and
1528
- * 2-extension combination in that table's universe without spinning up one
1529
- * real directory (and the full LSP-mocked tool) per combination — `hasMatch`
1530
- * is the only I/O-shaped seam, so the caller decides whether it is backed by
1531
- * a real `collectFiles` walk (production) or an in-memory extension-set probe
1532
- * (tests).
1533
- *
1534
- * Walks `SCAN_LANGUAGE_PRIORITY`'s FAMILIES in order and unions each member
1535
- * id's {@link extensionsForLanguage} into ONE `hasMatch` call — the first
1536
- * family with any match wins the whole directory for this pass. Grouping by
1537
- * family (not trying each id alone) is what makes a directory mixing BOTH
1538
- * extensions of a registry-split pair (`.ts`+`.tsx`, `.css`+`.scss`, ...)
1539
- * behavior-preserving vs the pre-#2434 bundled-key table: a flat per-id loop
1540
- * stopped at the first id with ANY match, silently losing the sibling half of
1541
- * a split pair present in the same directory (#2458 fix-round F1).
1542
- */
1543
- export async function resolveDirectoryScanExtensions(hasMatch) {
1544
- for (const family of SCAN_LANGUAGE_PRIORITY) {
1545
- const exts = family.flatMap((languageId) => extensionsForLanguage(languageId));
1546
- if (await hasMatch(exts)) {
1547
- return exts;
1548
- }
1549
- }
1550
- return undefined;
1551
- }
1552
- async function runDirectoryDiagnostics(absPath, severity, lspService, options) {
1553
- let collectedFiles = [];
1554
- const isIgnored = projectIgnorePredicate(absPath);
1555
- await resolveDirectoryScanExtensions(async (exts) => {
1556
- collectedFiles = await collectFiles(absPath, [...exts], MAX_FILES + 1, isIgnored);
1557
- return collectedFiles.length > 0;
1558
- });
1559
- if (collectedFiles.length === 0) {
1560
- return {
1561
- content: [
1562
- {
1563
- type: "text",
1564
- text: `No supported source files found in: ${absPath}`,
1565
- },
1566
- ],
1567
- details: {
1568
- filePath: absPath,
1569
- mode: "directory",
1570
- severity,
1571
- filesScanned: 0,
1572
- },
1573
- };
1574
- }
1575
- const wasCapped = collectedFiles.length > MAX_FILES;
1576
- const filesToProcess = collectedFiles.slice(0, MAX_FILES);
1577
- const { results, fileErrors, lspHealthWarnings, total, truncated, display, primaryDisplay, auxiliaryDisplay, clean, unconfirmed, timedOut, outcomeCounts, } = await collectBatchDiagnostics(filesToProcess, severity, lspService, options);
1578
- const navigationOnly = results.filter((result) => result.diagnosticsUnsupported).length;
1579
- // #3088: the directory scan's own suppressed bucket — one summed line.
1580
- const dispositionSuppressed = results.reduce((sum, result) => sum + (result.dispositionSuppressed ?? 0), 0);
1581
- const suppressedLine = dispositionSuppressedLine(dispositionSuppressed);
1582
- const outcomeDetails = results.map((result) => ({
1583
- file: result.file,
1584
- outcome: result.outcome,
1585
- reason: result.tooLargeReason ??
1586
- result.inconclusiveReason ??
1587
- result.error ??
1588
- result.unavailable,
1589
- }));
1590
- const tooLargeLines = renderBatchOutcomeLines(outcomeDetails, (file) => path.relative(absPath, file));
1591
- let text;
1592
- if (total === 0) {
1593
- // #533/#570: an unconfirmed-containing directory result must never
1594
- // render as a bare "no diagnostics" — that reads as an affirmative
1595
- // clean scan the server never actually gave for those files.
1596
- const cleanLine = unconfirmed > 0
1597
- ? `${clean} clean · ${unconfirmed} unconfirmed: ` +
1598
- `${unconfirmedReasonClause(unconfirmed, timedOut)} NOT the same as 0 diagnostics.`
1599
- : "No diagnostics found.";
1600
- text = [
1601
- `Directory: ${absPath}`,
1602
- `Files scanned: ${filesToProcess.length}${wasCapped ? ` (capped at ${MAX_FILES})` : ""}`,
1603
- ...(lspHealthWarnings.length > 0
1604
- ? [
1605
- "LSP unavailable for one or more files:",
1606
- ...lspHealthWarnings.slice(0, 10),
1607
- ]
1608
- : unconfirmed > 0 || outcomeCounts.clean === filesToProcess.length
1609
- ? [cleanLine]
1610
- : []),
1611
- ...(tooLargeLines.length > 0
1612
- ? ["", "Files too large for LSP diagnostics:", ...tooLargeLines]
1613
- : []),
1614
- ...(suppressedLine ? ["", suppressedLine] : []),
1615
- ].join("\n");
1616
- }
1617
- else {
1618
- const lines = [
1619
- `Directory: ${absPath}`,
1620
- `Files scanned: ${filesToProcess.length}${wasCapped ? ` (capped at ${MAX_FILES})` : ""}`,
1621
- `Files with errors: ${new Set(display.map((d) => d.file)).size}`,
1622
- `Total diagnostics: ${total}`,
1623
- ...(lspHealthWarnings.length > 0
1624
- ? ["", "LSP health warnings:", ...lspHealthWarnings.slice(0, 10)]
1625
- : []),
1626
- // #533/#570: the remaining clean-looking files in a mixed scan may
1627
- // still be unconfirmed — say so even though the directory as a
1628
- // whole found diagnostics elsewhere.
1629
- ...(unconfirmed > 0
1630
- ? [
1631
- "",
1632
- `${clean} other file${clean === 1 ? "" : "s"} confirmed clean, ${unconfirmed} unconfirmed: ` +
1633
- unconfirmedReasonClause(unconfirmed, timedOut),
1634
- ]
1635
- : []),
1636
- "",
1637
- ];
1638
- const toRelative = (d) => ({
1639
- ...d,
1640
- file: path.relative(absPath, d.file),
1641
- });
1642
- if (primaryDisplay.length > 0) {
1643
- lines.push(`Primary findings (${primaryDisplay.length}):`);
1644
- lines.push(...primaryDisplay.map(toRelative).map(formatDisplayDiag));
1645
- lines.push("");
1646
- }
1647
- if (auxiliaryDisplay.length > 0) {
1648
- lines.push(`Auxiliary findings (${auxiliaryDisplay.length}):`);
1649
- lines.push(...auxiliaryDisplay.map(toRelative).map(formatDisplayDiag));
1650
- }
1651
- if (truncated) {
1652
- lines.push("", `... (${total - MAX_DIAGNOSTICS} more diagnostics not shown)`);
1653
- }
1654
- if (suppressedLine)
1655
- lines.push("", suppressedLine);
1656
- if (tooLargeLines.length > 0) {
1657
- lines.push("", "Files too large for LSP diagnostics:", ...tooLargeLines);
1658
- }
1659
- text = lines.join("\n");
1660
- }
1661
- return {
1662
- content: [{ type: "text", text }],
1663
- details: {
1664
- filePath: absPath,
1665
- mode: "directory",
1666
- severity,
1667
- serverScope: options.serverScope ?? "all",
1668
- filesScanned: filesToProcess.length,
1669
- capped: wasCapped,
1670
- diagnostics: display.map((d) => ({
1671
- file: path.relative(absPath, d.file),
1672
- line: d.line,
1673
- character: d.character,
1674
- severity: d.severity,
1675
- message: d.message,
1676
- source: d.source,
1677
- code: d.code,
1678
- })),
1679
- primaryDiagnosticsCount: primaryDisplay.length,
1680
- auxiliaryDiagnosticsCount: auxiliaryDisplay.length,
1681
- totalDiagnostics: total,
1682
- ...(dispositionSuppressed > 0 && { dispositionSuppressed }),
1683
- truncated,
1684
- cleanFiles: clean,
1685
- unconfirmedFiles: unconfirmed,
1686
- outcomes: outcomeDetails,
1687
- outcomeCounts,
1688
- navigationOnlyFiles: navigationOnly > 0 ? navigationOnly : undefined,
1689
- timedOutFiles: timedOut > 0 ? timedOut : undefined,
1690
- fileErrors: fileErrors.length > 0 ? fileErrors : undefined,
1691
- lspHealthWarnings: lspHealthWarnings.length > 0 ? lspHealthWarnings : undefined,
1692
- concurrency: options.concurrency,
1693
- waitMs: options.waitMs,
1694
- },
1695
- };
1696
- }
1697
- // ── helpers ─────────────────────────────────────────────────────────────
1698
- /**
1699
- * #3088: the one rendering of the probe lane's policy drop, shared by the
1700
- * single-file, batch and directory renders so the three cannot word the same
1701
- * fact differently. Returns `undefined` when nothing was dropped — the #1616
1702
- * rule asks for a count when there IS one, not a "0 suppressed" line on every
1703
- * clean probe.
1704
- */
1705
- function dispositionSuppressedLine(suppressed) {
1706
- if (suppressed <= 0)
1707
- return undefined;
1708
- return (`suppressed by disposition: ${suppressed} finding(s) dropped from this ` +
1709
- "result because they're marked false-positive/won't-fix, disabled by " +
1710
- "`.pi-lens.json` rule policy, or suppressed by an inline `pi-lens-ignore` " +
1711
- "comment. Not a clean verdict for those locations — they were found, " +
1712
- "then intentionally hidden.");
1713
- }
1714
- function applySeverityFilter(diags, severity) {
1715
- if (severity === "all")
1716
- return diags;
1717
- const maxLevel = {
1718
- error: 1,
1719
- warning: 2,
1720
- information: 3,
1721
- hint: 4,
1722
- };
1723
- const max = maxLevel[severity] ?? 0;
1724
- if (max === 0)
1725
- return diags;
1726
- return diags.filter((d) => (d.severity ?? 3) <= max);
1727
- }
1728
- function formatDisplayDiag(d) {
1729
- const sevName = SEVERITY_NAMES[d.severity] ?? "unknown";
1730
- const loc = d.line !== undefined
1731
- ? `${d.file}:${d.line + 1}:${(d.character ?? 0) + 1}`
1732
- : d.file;
1733
- const src = d.source ? `[${d.source}]` : "";
1734
- const code = d.code ? ` (${d.code})` : "";
1735
- return `${loc}: ${sevName}${src}${code}: ${d.message}`;
1736
- }
1737
- function formatDiag(diag) {
1738
- const loc = diag.range?.start?.line !== undefined
1739
- ? `L${diag.range.start.line + 1}:${(diag.range.start.character ?? 0) + 1}`
1740
- : "";
1741
- const src = diag.source ? `[${diag.source}]` : "";
1742
- const code = diag.code ? ` (${diag.code})` : "";
1743
- const sevName = SEVERITY_NAMES[diag.severity] ?? "unknown";
1744
- return `${loc}: ${sevName}${src}${code}: ${diag.message}`;
1745
- }