@herbertgao/pi-extensions 2026.9.0 → 2026.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
  2. package/node_modules/@czottmann/pi-automode/README.md +20 -0
  3. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
  4. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
  5. package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
  6. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
  7. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
  8. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
  9. package/node_modules/@czottmann/pi-automode/package.json +1 -1
  10. package/node_modules/@narumitw/pi-btw/README.md +57 -141
  11. package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
  12. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
  13. package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
  14. package/node_modules/@narumitw/pi-btw/package.json +2 -1
  15. package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
  16. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
  17. package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
  18. package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
  19. package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
  20. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
  21. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
  22. package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
  23. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  24. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
  25. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  26. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  27. package/node_modules/pi-lens/CHANGELOG.md +1072 -0
  28. package/node_modules/pi-lens/README.md +3 -0
  29. package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
  30. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
  31. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -9
  32. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
  33. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
  34. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
  35. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
  36. package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
  37. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -9
  38. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
  39. package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -3
  40. package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
  41. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -6
  42. package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
  43. package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
  44. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
  45. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -9
  46. package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
  47. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +3 -11
  48. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
  49. package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
  50. package/node_modules/pi-lens/dist/clients/cache-observability.js +40 -19
  51. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
  52. package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -9
  53. package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
  54. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
  55. package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
  56. package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
  57. package/node_modules/pi-lens/dist/clients/config-core/index.js +50 -0
  58. package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
  59. package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
  60. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
  61. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +164 -0
  62. package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
  63. package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
  64. package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
  65. package/node_modules/pi-lens/dist/clients/config-core/schema.js +165 -0
  66. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
  67. package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
  68. package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
  69. package/node_modules/pi-lens/dist/clients/config-schema.js +234 -0
  70. package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
  71. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
  72. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -6
  73. package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
  74. package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
  75. package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
  76. package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
  77. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
  78. package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
  79. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
  80. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
  81. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +15 -5
  82. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
  83. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -44
  84. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +27 -8
  86. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
  87. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
  89. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
  90. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +383 -27
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +1 -2
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +14 -18
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +6 -3
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +1 -2
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +1 -2
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -3
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -67
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
  144. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -1
  145. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
  146. package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
  147. package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -10
  148. package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
  149. package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
  150. package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
  151. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
  152. package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
  153. package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
  154. package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
  155. package/node_modules/pi-lens/dist/clients/file-time.js +7 -2
  156. package/node_modules/pi-lens/dist/clients/file-utils.js +117 -10
  157. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
  158. package/node_modules/pi-lens/dist/clients/format-service.js +6 -2
  159. package/node_modules/pi-lens/dist/clients/formatters.js +385 -104
  160. package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
  161. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +116 -22
  162. package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
  163. package/node_modules/pi-lens/dist/clients/git-guard.js +6 -1
  164. package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
  165. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
  166. package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
  167. package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
  168. package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
  169. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
  170. package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
  171. package/node_modules/pi-lens/dist/clients/installer/index.js +289 -59
  172. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
  173. package/node_modules/pi-lens/dist/clients/instance-reaper.js +110 -236
  174. package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
  175. package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
  176. package/node_modules/pi-lens/dist/clients/language-registry.js +599 -0
  177. package/node_modules/pi-lens/dist/clients/latency-logger.js +165 -9
  178. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +34 -1
  179. package/node_modules/pi-lens/dist/clients/lens-config.js +160 -30
  180. package/node_modules/pi-lens/dist/clients/lens-engine.js +33 -41
  181. package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
  182. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +77 -6
  183. package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -38
  185. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
  186. package/node_modules/pi-lens/dist/clients/lsp/client.js +172 -33
  187. package/node_modules/pi-lens/dist/clients/lsp/config.js +484 -158
  188. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
  189. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
  190. package/node_modules/pi-lens/dist/clients/lsp/edits.js +18 -5
  191. package/node_modules/pi-lens/dist/clients/lsp/index.js +892 -96
  192. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
  193. package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -177
  194. package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
  195. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  196. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -18
  197. package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
  198. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
  199. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
  200. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
  201. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +14 -7
  202. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
  203. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
  204. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
  205. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
  206. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
  207. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
  208. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
  209. package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
  210. package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
  211. package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
  212. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +3 -5
  213. package/node_modules/pi-lens/dist/clients/module-report.js +21 -46
  214. package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
  215. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
  216. package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
  217. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -24
  218. package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
  219. package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
  220. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +70 -28
  221. package/node_modules/pi-lens/dist/clients/opengrep-config.js +5 -1
  222. package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
  223. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
  224. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
  225. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
  226. package/node_modules/pi-lens/dist/clients/path-utils.js +451 -15
  227. package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
  228. package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
  229. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
  230. package/node_modules/pi-lens/dist/clients/pipeline.js +79 -18
  231. package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
  232. package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
  233. package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
  234. package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
  235. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
  236. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
  237. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
  238. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
  239. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
  240. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
  241. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +28 -4
  242. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
  243. package/node_modules/pi-lens/dist/clients/project-lens-config.js +438 -122
  244. package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
  245. package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
  246. package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
  247. package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
  248. package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
  249. package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
  250. package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
  251. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +16 -5
  252. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
  253. package/node_modules/pi-lens/dist/clients/read-guard.js +26 -2
  254. package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
  255. package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
  256. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +155 -114
  257. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
  258. package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
  259. package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
  260. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
  261. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
  262. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +19 -3
  263. package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
  264. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
  265. package/node_modules/pi-lens/dist/clients/runtime-session.js +184 -32
  266. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +179 -36
  267. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
  268. package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
  269. package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
  270. package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
  271. package/node_modules/pi-lens/dist/clients/sanitize.js +7 -12
  272. package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
  273. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
  274. package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
  275. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
  276. package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
  277. package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
  278. package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
  279. package/node_modules/pi-lens/dist/clients/sgconfig.js +7 -6
  280. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
  281. package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
  282. package/node_modules/pi-lens/dist/clients/smells-rollup.js +4 -4
  283. package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
  284. package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
  285. package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
  286. package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
  287. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +244 -0
  288. package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
  289. package/node_modules/pi-lens/dist/clients/tool-policy.js +92 -22
  290. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
  291. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +87 -100
  292. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  293. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
  294. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
  295. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
  296. package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
  297. package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
  298. package/node_modules/pi-lens/dist/clients/user-notify.js +6 -6
  299. package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
  300. package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -9
  301. package/node_modules/pi-lens/dist/clients/word-index-store.js +23 -12
  302. package/node_modules/pi-lens/dist/clients/word-index.js +252 -47
  303. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
  304. package/node_modules/pi-lens/dist/clients/zizmor-config.js +4 -1
  305. package/node_modules/pi-lens/dist/index.js +65899 -55340
  306. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
  307. package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
  308. package/node_modules/pi-lens/dist/mcp/server.js +127 -5
  309. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
  310. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
  311. package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
  312. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +96 -25
  313. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +104 -86
  314. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
  315. package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
  316. package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
  317. package/node_modules/pi-lens/dist/tools/shared.js +0 -1
  318. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
  319. package/node_modules/pi-lens/docs/agent-guide.md +64 -1
  320. package/node_modules/pi-lens/docs/configuration.md +222 -0
  321. package/node_modules/pi-lens/docs/dependencies.md +3 -3
  322. package/node_modules/pi-lens/docs/features.md +44 -5
  323. package/node_modules/pi-lens/docs/globalconfig.md +20 -0
  324. package/node_modules/pi-lens/docs/language-coverage.md +2 -2
  325. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
  326. package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
  327. package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
  328. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +33 -0
  329. package/node_modules/pi-lens/docs/pi-lens-subagent.md +49 -0
  330. package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
  331. package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
  332. package/node_modules/pi-lens/docs/release-qa-baseline.md +190 -0
  333. package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
  334. package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
  335. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
  336. package/node_modules/pi-lens/docs/word-index.md +1 -1
  337. package/node_modules/pi-lens/package.json +18 -35
  338. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
  339. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
  340. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
  341. package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
  342. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
  343. package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
  344. package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
  345. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
  346. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
  347. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
  348. package/node_modules/pi-web-access/CHANGELOG.md +28 -0
  349. package/node_modules/pi-web-access/README.md +62 -15
  350. package/node_modules/pi-web-access/curator-page.ts +3 -1
  351. package/node_modules/pi-web-access/curator-server.ts +5 -1
  352. package/node_modules/pi-web-access/gemini-search.ts +8 -4
  353. package/node_modules/pi-web-access/github-extract.ts +242 -1
  354. package/node_modules/pi-web-access/index.ts +118 -64
  355. package/node_modules/pi-web-access/mistral-search.ts +281 -0
  356. package/node_modules/pi-web-access/package.json +2 -2
  357. package/node_modules/pi-web-access/perplexity.ts +14 -1
  358. package/node_modules/pi-web-access/utils.ts +23 -6
  359. package/node_modules/pi-web-access/xai-search.ts +96 -33
  360. package/package.json +6 -6
@@ -0,0 +1,359 @@
1
+ # Public API stability and versioning policy
2
+
3
+ **Status:** normative. Landed by #2418; gates #2416.
4
+ **Enforced by:** `clients/config-diagnostic-codes.ts` (the data),
5
+ `tests/support/schema-stability.ts`, `tests/config/schema-stability-tiers.test.ts`,
6
+ `tests/clients/config-diagnostic-codes.test.ts`,
7
+ `tests/clients/config-deprecation-registry.test.ts` (the tests).
8
+
9
+ pi-lens ships to roughly 28k installs a month. A config field, a warning a user
10
+ greps for, or a tool id becomes a compatibility obligation the moment it ships —
11
+ whether or not anyone wrote that obligation down. This document writes it down,
12
+ and every clause below is backed by a test rather than by convention, because a
13
+ policy nobody can fail is not a policy.
14
+
15
+ Scope: the unified config schema (#2415/#2416/#2383/#195), the capability
16
+ facades, the MCP tool mirror, and the versioned `PiLensApi` (#1358). It does not
17
+ define any catalog schema; it constrains how those schemas evolve.
18
+
19
+ ## 1. Field stability tiers
20
+
21
+ Every property in a published pi-lens schema carries an `x-stability`
22
+ annotation, whose value is one of a closed vocabulary:
23
+
24
+ | Tier | Meaning |
25
+ | --- | --- |
26
+ | `experimental` | May change shape, semantics, or disappear in a **minor** release. Not covered by the compatibility guarantee. |
27
+ | `stable` | Covered by the guarantee. Shape and semantics change only in a **major**, through the checklist in section 4. |
28
+
29
+ Rules:
30
+
31
+ - **New fields default to `experimental`.** Shipping a field straight to
32
+ `stable` is a deliberate act, not a default.
33
+ - **Promotion `experimental` → `stable` is changelogged** under `Changed`,
34
+ naming the field. Demotion `stable` → `experimental` is a breaking change and
35
+ follows section 4.
36
+ - **A property with no tier fails CI.** `assertSchemaStabilityTiers` walks the
37
+ whole schema — `properties`, `patternProperties`, `items`, `prefixItems`,
38
+ `additionalProperties`, `oneOf`/`anyOf`/`allOf`, `not`, `if`/`then`/`else`,
39
+ `$defs`/`definitions` — so a field cannot hide from the tier requirement by
40
+ living inside a composition keyword.
41
+ - The **root schema** is not itself a property and carries no tier. Entries
42
+ under `$defs`/`definitions` are reusable subschemas, not published fields;
43
+ they need no tier, but every property *inside* them does.
44
+
45
+ The vocabulary lives in `STABILITY_TIERS` and the annotation key in
46
+ `STABILITY_TIER_KEY` (`clients/config-diagnostic-codes.ts`). #2416's first real
47
+ catalog schema asserts itself with the same two exported functions rather than
48
+ writing a second walker.
49
+
50
+ ## 2. Stable config diagnostic codes
51
+
52
+ Every user-facing config validation or migration warning carries a code from a
53
+ closed, **append-only** namespace, `PILENS_CFG_NNNN`, registered once in
54
+ `CONFIG_DIAGNOSTIC_CODES`.
55
+
56
+ - **The prose is not API; the code is.** Message text may be rewritten in any
57
+ release. A code is never renumbered, never removed, and a retired number is
58
+ never reused — a retired code keeps its registry entry with an amended
59
+ description.
60
+ - The code is threaded through the one durable choke point
61
+ (`recordDegradationOnce` / `incrementDegradationCount` in
62
+ `clients/degradation-ledger.ts`) and through `notifyUserDegradation`, so the
63
+ same code appears in the user-visible message, in `extension.log`, and in the
64
+ durable `latency.log` degradation row.
65
+ - The durable row writes `code` **after** the bounded caller metadata, so the
66
+ ledger's `MAX_METADATA_KEYS` cap can never evict the one field a user greps
67
+ on.
68
+ - A new `notifyUserDegradation` call from any `clients/**/*config*.ts` file
69
+ without a registered code fails CI
70
+ (`tests/clients/config-diagnostic-codes.test.ts` scans for it; it does not
71
+ keep a hand-maintained list of call sites).
72
+
73
+ ### How a user matches or suppresses a warning
74
+
75
+ **The match key is the bracketed suffix, not the prose.** Every coded warning is
76
+ rendered as:
77
+
78
+ ```
79
+ pi-lens: ignoring invalid LSP config .pi-lens/lsp.json: Unexpected token } [PILENS_CFG_0001]
80
+ ```
81
+
82
+ The trailing ` [PILENS_CFG_NNNN]` marker is appended by
83
+ `withConfigDiagnosticCode`, is idempotent, and is always last. Match on it:
84
+
85
+ ```sh
86
+ # every ignored-config warning this session, from the durable degradation log
87
+ grep 'PILENS_CFG_0001' ~/.pi-lens/latency.log
88
+
89
+ # suppress one code while keeping every other pi-lens warning
90
+ pi ... 2>&1 | grep -v 'PILENS_CFG_0001'
91
+ ```
92
+
93
+ The extraction pattern is exported as `CONFIG_DIAGNOSTIC_MARKER_PATTERN`
94
+ (capture group 1 is the code) so tooling need not re-derive it. Anything that
95
+ filters on the prose instead — `"ignoring invalid"` — is filtering on a string
96
+ this policy explicitly reserves the right to change.
97
+
98
+ ### Registered codes
99
+
100
+ | Code | Meaning | Emitter |
101
+ | --- | --- | --- |
102
+ | `PILENS_CFG_0001` | A config file exists but could not be read or parsed, so it is ignored. | `warnIgnoredConfigOnce` (`clients/config-warn.ts`), the single choke point behind the LSP, global, and project config loaders. |
103
+ | `PILENS_CFG_0002` | A deprecated config **key** was accepted inside its deprecation window. | `deprecationRecords` (`clients/config-resolve.ts`), one record per `(file, key)`, delivered by `reportPiLensConfigRecords` (#2426). |
104
+ | `PILENS_CFG_0003` | A deprecated config **file location** was read inside its window. | Same producer and same delivery path as `PILENS_CFG_0002`. |
105
+ | `PILENS_CFG_0004` | A config field no schema property claims was dropped. | `validate()` (`clients/config-core/normalize.ts`) produces the record; `reportPiLensConfigRecords` (`clients/config-resolve.ts`) delivers it through `warnIgnoredConfigOnce` (#2426). |
106
+ | `PILENS_CFG_0005` | A config field's value did not match its schema and was dropped. One FIELD; the rest of the file is in effect. | Same producer and same delivery path as `PILENS_CFG_0004`. |
107
+ | `PILENS_CFG_0006` | A config key that would modify an object's prototype (`__proto__`, `constructor`, `prototype`) was refused. | Both halves of the config core, through the shared policy in `clients/config-core/safe-object.ts`. |
108
+ | `PILENS_CFG_0007` | Further config notices were suppressed by a bound, and this one carries the count — the WHOLE count, including anything an earlier bound in the same pipeline dropped. Nothing about the config is wrong; the notice list was truncated. | `MigrationRecordCollector.finalize` (`clients/config-core/records.ts`) — the ONE producer, reached through `finalizeRecords` by every record list: the shared resolution, the global loader's unknown-key scan, the project loader's unknown-key scan, and its legacy-document enumeration. Rendered with neutral prose and recorded under the `config-notice-suppressed` degradation kind, never `config-ignored`. |
109
+ | `PILENS_CFG_0008` | Resolving a config failed internally, so the WHOLE file was ignored and pi-lens ran on defaults. | The two guards under the pipeline: `resolveConfig` (`clients/config-core/resolve.ts`) and the global loader's post-parse catch (`clients/lens-config.ts`). Carries the error class only, never its message. |
110
+
111
+ A reserved code is registered and referenced by the deprecation registry, but
112
+ nothing emits it today. That is deliberate: the number must be pinned before the
113
+ migration warning ships, because append-only means the number cannot be chosen
114
+ later.
115
+
116
+ ## 3. Config-envelope identity anchor
117
+
118
+ The unified config format reserves a `$schema` URL from its first published
119
+ version. Both halves are pinned in `clients/config-diagnostic-codes.ts`:
120
+
121
+ - `CONFIG_SCHEMA_ID` — the canonical schema URL. The published schema's own
122
+ `$id` must equal it.
123
+ - `CONFIG_SCHEMA_ANCHOR_KEY` (`"$schema"`) — the key a user's config file uses
124
+ to name the schema it was written against.
125
+
126
+ `assertSchemaIdentityAnchor` checks all three facts: the schema's `$id` matches,
127
+ the schema declares a meta-schema, and the root declares a `$schema` **instance**
128
+ property so a user's file can carry the anchor. Pinning the URL in one module is
129
+ what stops it drifting between the schema, the validator, and the docs.
130
+
131
+ ## 4. Deprecation window and removal checklist
132
+
133
+ ### The maintainer stance
134
+
135
+ **A legacy source is read for exactly one deprecation window, and then it is
136
+ actually removed.** pi-lens does not carry legacy config surfaces forever, and
137
+ it does not silently drop them either. Both failure modes are ruled out by the
138
+ same rule: while a surface is inside its window it is read and honored exactly
139
+ as before, with a bounded coded warning; at the next major it is removed through
140
+ the checklist below, announced in `Removed`. Nothing is ever dropped without an
141
+ announced window that preceded it.
142
+
143
+ ### The data
144
+
145
+ Every deprecated key or file location is a row in `DEPRECATED_CONFIG_SURFACES`
146
+ carrying `surface`, `kind`, `code`, `deprecatedSince`, `removeNotBefore`, and a
147
+ `reason`. The registry test enforces:
148
+
149
+ - `deprecatedSince` names the release that **announces** the deprecation — for a
150
+ row announced only in an unreleased `.changelog/` fragment, that must be a
151
+ version later than the newest release in `CHANGELOG.md` (you cannot back-date
152
+ a deprecation into a version that already shipped without it);
153
+ - `removeNotBefore` is a **later major**, `X.0.0` — removal never happens in a
154
+ minor;
155
+ - the row's code is registered, and matches its kind;
156
+ - the surface is announced in a Changelog `Deprecated` section as a delimited
157
+ token (`` `pi-lens.json` ``), so a substring of a longer filename does not
158
+ count as an announcement;
159
+ - FILE rows name a location a loader actually reads, and KEY rows name a key the
160
+ `LSPConfig` interface actually declares — both checked against the exported
161
+ constants and the real interface body, never a hand-copied list.
162
+
163
+ Note that a canonical file is not deprecated because some of its keys are.
164
+ `.pi-lens.json` is a canonical location (#2426); the deprecated surfaces are the
165
+ legacy top-level LSP keys read from it, which are `kind: "key"` rows.
166
+
167
+ ### The removal checklist
168
+
169
+ This is the checklist #2372 slice 5's "separately approved breaking-change plan"
170
+ instantiates. It does not invent a second process; slice 5 is one execution of
171
+ this list.
172
+
173
+ 1. **Window elapsed.** The current version is at or past the row's
174
+ `removeNotBefore`, and that version is a major.
175
+ 2. **Announced.** The surface has been in a shipped `Deprecated` changelog
176
+ section since `deprecatedSince`, continuously.
177
+ 3. **Warned in-product.** The migration warning has been emitting its stable
178
+ code for the whole window — the user has had a coded, greppable signal, not
179
+ only a release note.
180
+ 4. **Migration path documented and reachable.** The replacement surface exists,
181
+ is `stable`, and the `reason` field names it.
182
+ 5. **Canonical-wins collision behavior verified.** For the whole window, a
183
+ config setting both the legacy and the canonical surface resolved to the
184
+ canonical one, with the coded warning naming the ignored legacy value.
185
+ 6. **Removal PR does all four:** deletes the reader, deletes the registry row,
186
+ adds a `Removed` changelog entry naming the surface and the replacement, and
187
+ keeps the diagnostic code registered (codes outlive the surfaces they
188
+ described).
189
+ 7. **Approved as a breaking change.** A major-version bump plus explicit
190
+ maintainer approval on the plan; a removal never rides in on an unrelated PR.
191
+
192
+ Removing a row from `DEPRECATED_CONFIG_SURFACES` while the reader still exists,
193
+ or removing the reader while the row still exists, fails the registry test. The
194
+ two move together or not at all.
195
+
196
+ ## 5. The config core
197
+
198
+ `clients/config-core/` is the one place a pi-lens configuration is validated,
199
+ merged, and explained. Every loader, catalog, and selector resolves through it
200
+ (#2425); a fourth merge semantics is a defect, not a design choice.
201
+
202
+ The pipeline is `RawConfig -> validate(schema) -> NormalizedConfig ->
203
+ merge(sources) -> Resolved<T>`, and `resolveConfig` runs both halves. It is
204
+ pure: no file reads, no logging, no ledger writes. Reporting is the separate,
205
+ explicit `reportPiLensConfigRecords` step (`clients/config-resolve.ts`, which is
206
+ where the loaders share it — never inside the core), so the warn-once latch
207
+ stays with the loaders rather than with the library.
208
+
209
+ Every loader reports **every** record its own resolution produced — it does not
210
+ filter to the records it "owns". Ownership is a property of the RECORD, not of
211
+ the caller: `reportPiLensConfigRecords` derives the reporting subsystem from the
212
+ record's own owner and tier, so an `lsp.*` key always reports as an LSP setting
213
+ and a pi-lens key always reports under the loader for its tier, whichever loader
214
+ happened to open the file. A `(file, key)` that three loaders all resolve is
215
+ reported three times and the warn-once latch — keyed on
216
+ `(subsystem, file, key, reason)` — collapses those into the one notice the user
217
+ sees. Filtering by caller instead is what left a record no loader claimed
218
+ reported by nobody at all (#2426 review round 3, F1).
219
+
220
+ ### Source tiers
221
+
222
+ Seven tiers, lowest value-precedence first. A later tier's value replaces an
223
+ earlier one for the same leaf.
224
+
225
+ | Tier | Class | Meaning |
226
+ | --- | --- | --- |
227
+ | `builtin` | **default** | pi-lens's own shipped defaults. |
228
+ | `global` | operator | The user's machine-global config. |
229
+ | `project` | **repo** | A config file inside the checkout. |
230
+ | `nested-project` | **repo** | A config file in a nested package. |
231
+ | `env` | operator | Environment variables. |
232
+ | `cli` | operator | Command-line arguments. |
233
+ | `host` | operator | The host application's decision. |
234
+
235
+ The class column is a second, independent axis, and it has **three** values, not
236
+ two. `repo` tiers carry content that arrived with a checkout — content a user
237
+ may never have read. `operator` tiers are a deliberate act by the person running
238
+ pi-lens. `default` is pi-lens's own shipped opinion, which nobody chose. Only the
239
+ class decides who may lift a denial; `builtin` being its own class is what keeps
240
+ a shipped default overridable by the operator while still out of reach of
241
+ repository content.
242
+
243
+ ### Monotonic deny precedence
244
+
245
+ A schema node marked `x-deny` resolves by denial rules instead of
246
+ last-tier-wins:
247
+
248
+ - `x-deny: "boolean-false"` — a `false` from an **operator** tier is never
249
+ lifted, by anything. A `false` from a `default` or `repo` tier is lifted only
250
+ by an explicit `true` from an **operator** tier of higher precedence. A repo
251
+ tier never lifts a denial at all, its own class included.
252
+ - `x-deny: "array-union"` — the resolved list is the union of every tier's
253
+ members. There is no vocabulary for un-denying a member, so a nearer tier that
254
+ omits one is expressing nothing. This outranks the node's own
255
+ `x-merge-strategy`: a denial a merge strategy could erase would not be
256
+ monotonic.
257
+
258
+ Provenance for a denied leaf names the tier that **made** the denial, not the
259
+ last tier to restate it — the answer to "why can I not turn this back on".
260
+
261
+ Two consequences are deliberate rulings rather than accidents of the algorithm,
262
+ and both are load-bearing:
263
+
264
+ **A built-in denial is a default, not a law.** `builtin: false` plus
265
+ `global: true` resolves to `true`, attributed to `global`; `builtin: false` plus
266
+ `project: true` stays `false`, attributed to `builtin`. When `builtin` sat in the
267
+ operator class, a conservative default pi-lens shipped — an `enabled: false`, or
268
+ any member of a built-in deny list — could never be lifted by anyone, including
269
+ the person who installed pi-lens, and the only escape was editing pi-lens's
270
+ source. A default the operator cannot override is not a default.
271
+
272
+ **An operator denial is not liftable by a nearer operator tier.** `global: false`
273
+ plus `cli: true` stays `false`. This is the spec letter and it is kept on
274
+ purpose: a denial is a security decision, and letting one operator surface
275
+ out-shout another would make the guarantee depend on which surface an attacker
276
+ could reach (an inherited `PILENS_*` environment variable, a wrapper script's
277
+ argv) rather than on what the operator decided. The escape hatch is an
278
+ operator-tier **change** — edit the global config, unset the variable — never a
279
+ repo-tier one.
280
+
281
+ ### Prototype-safe keys
282
+
283
+ `__proto__`, `constructor`, and `prototype` are refused wherever a config
284
+ supplies a key, in both halves of the pipeline, with a `PILENS_CFG_0006` record
285
+ naming the key. No pi-lens setting is spelled that way, so there is nothing to
286
+ preserve, and assigning one would change an object's behavior rather than its
287
+ contents — a document that serializes as `{}` while answering an attacker's
288
+ value on every field read.
289
+
290
+ Both halves also bound their own recursion at `MAX_CONFIG_DEPTH` (32) and
291
+ `resolveConfig` never throws: a config that cannot be resolved degrades to
292
+ absent with records, never to a failed session.
293
+
294
+ A schema node that declares no `type` — or a `type` keyword the core does not
295
+ recognize — is **opaque**, and an opaque node is walked by the value's own
296
+ shape rather than passed through. Its children are kept (that is what an opaque
297
+ node means), but they are copied, depth-counted, key-checked, and recorded like
298
+ any other. A schema that wants a genuinely free-form subtree should still say
299
+ `additionalProperties: true`, which states the intent instead of relying on an
300
+ omission.
301
+
302
+ ### Merge strategies
303
+
304
+ Objects are always merged field-wise; a nearer tier setting one key never erases
305
+ its siblings. Arrays follow the node's `x-merge-strategy`:
306
+
307
+ | Value | Behavior |
308
+ | --- | --- |
309
+ | `replace` (default) | The highest-precedence tier that sets the array supplies all of it. |
310
+ | `append` | Every tier's entries, concatenated lowest precedence first. |
311
+ | `keyed:<field>` | Entries matched across tiers by `<field>` and merged field-wise; unmatched entries appended. |
312
+
313
+ ### The trust-gated `ProcessSpec`
314
+
315
+ A `ProcessSpec` carries a non-empty argv, a bounded env (count and bytes), a
316
+ closed `cwdMode`/`inputMode`, a timeout, its provenance, and the trust decision
317
+ that applied when it was read. `toSpawnArgs(spec)` is the only way to get
318
+ spawnable arguments out of one, and for a `project` or `nested-project` spec it
319
+ refuses unless **both** the spec's recorded trust and the host's current
320
+ `isProjectTrusted()` decision are `"trusted"`. Two conditions, because a session
321
+ can revoke trust after the config was read; one condition would make a spec a
322
+ permanent capability token.
323
+
324
+ `unknown` fails closed here, unlike `isToolInstallAllowedByTrust`. That gate
325
+ governs pi-lens's own managed tools; this one governs a command string a
326
+ repository wrote.
327
+
328
+ Refusals record under the existing `trust-refusal` degradation kind through
329
+ `incrementDegradationCount`, carrying the tier, `argv[0]`, and the trust
330
+ generation — never an argument or an env value.
331
+
332
+ ### Redaction
333
+
334
+ `redactProcessSpec` is the only projection of a spec for a diagnostic or
335
+ telemetry surface. It strips every env **value** and every argv entry after
336
+ `argv[0]`; env names survive, because a name is a label and "which variables did
337
+ this server get" is the question an operator asks.
338
+
339
+ `provenanceView(resolved)` is redacted by construction: it is built from the
340
+ provenance map alone and never reads the resolved value, so no un-redacted view
341
+ exists. Validation records are bounded and structural — a reason names a key, a
342
+ type, and a count, never a value or a source snippet.
343
+
344
+ ## Where each policy point is enforced
345
+
346
+ | Policy point | Data | Test |
347
+ | --- | --- | --- |
348
+ | 1. `x-stability` on every published field | `STABILITY_TIER_KEY`, `STABILITY_TIERS` | `tests/config/schema-stability-tiers.test.ts` via `assertSchemaStabilityTiers` |
349
+ | 2. Append-only `PILENS_CFG_*` codes | `CONFIG_DIAGNOSTIC_CODES` | `tests/clients/config-diagnostic-codes.test.ts` |
350
+ | 3. Reserved `$schema` identity anchor | `CONFIG_SCHEMA_ID`, `CONFIG_SCHEMA_ANCHOR_KEY` | `assertSchemaIdentityAnchor` |
351
+ | 4. Deprecation window + removal checklist | `DEPRECATED_CONFIG_SURFACES` | `tests/clients/config-deprecation-registry.test.ts` |
352
+ | 5. Config core: tiers, deny precedence, ProcessSpec trust | `clients/config-core/` | `tests/clients/config-core/*.test.ts`, `tests/config/config-core-schema-stability.test.ts` |
353
+
354
+ ## Related
355
+
356
+ #2415 (shared config core), #2416/#2372 (catalog schema and its compat
357
+ template), #2383, #195 (selector semantics), #1358 (facade versioning — a
358
+ separate version axis this policy only has to compose with), #2426 (canonical
359
+ config locations).
@@ -0,0 +1,190 @@
1
+ # Release-QA baseline matrix
2
+
3
+ The feature × modality matrix a release candidate is witnessed against before a
4
+ tag is cut. `scripts/release-qa.mjs` reads THIS FILE — the table below is the
5
+ runner's row list, not a copy of one — exports the committed tree, packs and
6
+ installs the candidate into a scratch `HOME`, drives each row's entry point
7
+ against a real `pi`, and writes `release-qa-report.md` plus one witness file per
8
+ row under `release-qa-evidence/`.
9
+
10
+ Every child process the runner spawns — `pi`, the MCP server, `node`, `npm` —
11
+ runs under a pinned environment: `HOME`, `USERPROFILE`, `PI_LENS_HOME`,
12
+ `PILENS_DATA_DIR`, `PI_LENS_INSTALL_LOG` and `npm_config_cache` all inside the
13
+ scratch root. `PI_LENS_INSTALL_LOG` is on that list by hard experience: it is
14
+ what `scripts/warm-loader-cache.mjs` keys its install log on, with
15
+ `PI_LENS_HOME/install.log` as the fallback when it is unset, and the runner's
16
+ first six runs — which pinned the pi-lens home but passed no environment to
17
+ `npm` at all — put 41 records into the maintainer's real
18
+ `~/.pi-lens/install.log` (#2619 review F1). The pack runs in a
19
+ `git archive HEAD` export, never the live checkout, because `npm pack` fires our
20
+ own `prepack` (rewrites `package.json` + `package-lock.json`) and `prepare`
21
+ (rebuilds `dist/`, downloads grammars, reinstalls git hooks).
22
+
23
+ Why it exists: #2587. The four shipped skills were suspected of never
24
+ registering for four releases because **no check ever asked a real pi what it
25
+ loaded**. The unit suite (~10.8k tests) and the nightly smokes (install, compat,
26
+ tool, lifecycle, parser) are per-seam; nothing composed them into a release
27
+ verdict with counted coverage, so a missing row read as absence rather than
28
+ arithmetic.
29
+
30
+ ## Reading the table
31
+
32
+ - **row id** — the runner's key. Every id here must have a probe in
33
+ `scripts/release-qa.mjs`, and every probe there must appear here; the tie is
34
+ enforced by `tests/scripts/release-qa.test.ts`, so neither list can drift into
35
+ a hand-maintained mirror of the other.
36
+ - **entry point** — the command or RPC a **user path** actually takes. Never a
37
+ raw internal function: a row whose entry point is an internal call proves the
38
+ function works, not the product.
39
+ - **pass criterion** — the concrete thing the witness must SHOW (a status, a
40
+ count, a named record). "It ran without throwing" is not a criterion.
41
+ - **witness** — the artifact captured under `release-qa-evidence/`. A witness
42
+ that merely exists is not a witness; the report quotes the line that shows the
43
+ asserted result.
44
+ - **reuse** — the existing script that already produces this witness, or the
45
+ smoke that would have caught this row's regression. `new` means nothing in the
46
+ repo covers it, and the cell says so rather than leaving the gap implicit.
47
+ - **umbrella** — the open smoke-umbrella issue whose scope this row overlaps
48
+ (#1605 lifecycle/real-host lanes, #1829 tool-contract lanes), with one line on
49
+ where the two differ. `—` means neither umbrella claims this ground. This
50
+ column exists so a reader can tell at a glance which rows are a down-payment
51
+ on an already-filed umbrella and which are genuinely uncovered — and so the
52
+ umbrella issues are not re-litigated row by row when they are eventually
53
+ built.
54
+
55
+ ## Modalities
56
+
57
+ | modality | what it stands for |
58
+ | --- | --- |
59
+ | `npm-pack` | the published artifact itself — what `npm publish` uploads |
60
+ | `npm-install` | a user installing the tarball into a project's `node_modules` |
61
+ | `pi-rpc` | pi loading the installed package, driven headless via `pi --mode rpc` |
62
+ | `mcp-stdio` | an MCP client speaking JSON-RPC to `dist/mcp/server.js` |
63
+ | `git-install` | `pi install git:...` against a pushed ref |
64
+
65
+ Static packaging shape under `npm-pack` is NOT a matrix row: CI's
66
+ `ci.yml` `prod-install-build` job already runs `publint` (gating) on every
67
+ PR's packed tarball (#2700, the check #2587 was missing). `attw`
68
+ (arethetypeswrong) is not run there or here — the package ships no
69
+ `.d.ts` at all (`tsconfig.dist.json` sets `"declaration": false`, no
70
+ `types`/`exports` in `package.json`), so there is nothing for it to grade.
71
+
72
+ ## The matrix
73
+
74
+ | row id | feature | modality | entry point | pass criterion | witness | reuse | umbrella |
75
+ | --- | --- | --- | --- | --- | --- | --- | --- |
76
+ | pack-skills-payload | the four shipped skills and the compiled entry are IN the published artifact | npm-pack | `npm pack --json` on the release candidate | packed file list contains `dist/index.js` and at least 4 `skills/**/SKILL.md` | pack listing JSON | new — `tests/packaging.test.ts` asserts `files[]` NAMES `skills/`, never that the pack carries SKILL.md files | — |
77
+ | install-selftest | the runtime dependency graph and the `pi.skills` manifest resolve AS INSTALLED | npm-install | `node <installed>/scripts/install-selftest.mjs --allow-soft` | process exits 0 and no `[FAIL]` line | selftest stdout | `scripts/install-selftest.mjs` verbatim — install-smoke's `smoke` job | #1605 lane 5 (real-host install), narrower: this row asserts the packaged artifact resolves, not that a host classifier parses |
78
+ | skills-registered | a real pi registers the four pi-lens skills from the installed package | pi-rpc | `pi install <installed pkg>` then `pi --mode rpc` plus `{"type":"get_commands"}` | at least 4 commands with `source` `skill`; every `sourceInfo.path` inside the installed package AND every `sourceInfo.source` equal to `extension:index` | get_commands response JSON | new probe on the #2589 mechanism — the recurrence is #2587 | — |
79
+ | commands-registered | the extension loads and registers its `lens-*` slash commands | pi-rpc | same RPC session as above | at least 1 command with `source` `extension` named `lens-*`, and zero `extension_error` events | same get_commands response plus the event stream | `scripts/rpc-load-check.mjs` assertion — install-smoke's `pi-load` job, which runs it against the PUBLISHED package only | #1605 lane 1 (real-host): the same real-host principle, applied to extension registration rather than stderr classification |
80
+ | mcp-tools-registered | the MCP mirror advertises the `pilens_*` tool surface | mcp-stdio | `node <installed>/dist/mcp/server.js` then `initialize` plus `tools/list` | every advertised tool name starts `pilens_`, and the set contains analyze, diagnostics, turn_end, lsp_navigation, health | tools/list response JSON | new — no smoke drives the MCP mirror from an install | — |
81
+ | mcp-diagnostics-full | `lens_diagnostics` full mode answers on a fixture repo | mcp-stdio | `tools/call` `pilens_diagnostics` with `mode` `full` and `refreshRunners` `cheap`, POLLED | text carries a `Summary (N files diagnosed this session)` line with N at least 1 | tool result text | new — `tests/clients` covers the handler, nothing covers it through a packaged install | — |
82
+ | mcp-turn-end | the turn-end pipeline runs over the turn's files and returns an advisory | mcp-stdio | `tools/call` `pilens_turn_end` with the fixture file | text carries `Turn-end over N file(s).` with N at least 1 | tool result text | new — `scripts/smoke-availability-lifecycle.mjs` covers lifecycle availability, not the packaged turn-end path | #1605 lane 2 (availability-lifecycle): overlaps the turn-end half; #1605 asserts latch recovery, this row asserts the packaged turn-end path answers at all |
83
+ | mcp-lsp-navigation | LSP navigation answers on a fixture | mcp-stdio | `tools/call` `pilens_lsp_navigation` with operation `documentSymbol` and the fixture path | result is not an error and names the fixture's exported `releaseQaFixtureSymbol` | tool result text | `scripts/smoke-tools.mjs --lsp` is the per-server sibling; this row is the packaged-path variant | #1829 lane 2/3 (gated real-binary + the rotating install lane): #1829 pins each tool's own contract, this row pins that the packaged LSP path answers |
84
+ | config-provenance | a project config is LOADED and its provenance is reportable | mcp-stdio | `tools/call` `pilens_effective_config` with the fixture file | result names the fixture's `.pi-lens.json` as a contributing document | tool result text | new — `tests/config/pi-lens-config-schema.test.ts` covers the schema, not the packaged load | — |
85
+ | degradation-visible | a silently-ignored input is RECORDED as a degradation instead of vanishing | mcp-stdio | `tools/call` `pilens_health` with the fixture's project-tier `lsp.enabled` (a global-only setting) loaded | health text carries a `config-ignored` degradation line naming the fixture's `.pi-lens.json` | health tool result text | `clients/degradation-ledger.ts` is the reused machinery; no smoke asserts it end to end | #1605 lane 2 (availability-lifecycle): the degradation-recorded half; #1605 additionally asserts RECOVERY, which this row does not |
86
+ | git-install-loads | a `git:` install of a pushed ref builds and loads in a real pi | git-install | `pi install git:github.com/apmantza/pi-lens@<ref>` then `get_commands` | at least 1 `lens-*` command and at least 4 skills | get_commands response JSON | `scripts/rpc-load-check.mjs` assertion, re-run against the git layout | — |
87
+
88
+ ## Why `skills-registered` pins the registrar
89
+
90
+ pi-lens has **two independent skill registrars**: the `pi.skills` manifest, and
91
+ `index.ts`'s own `resources_discover` handler (#205,
92
+ `resolvePackagePath(import.meta.url, "skills")`), which never reads the
93
+ manifest. #2587 is the proof that one half can be broken for four releases while
94
+ the other silently covers for it — driving published pi-lens 4.1.3, with the
95
+ broken `["../../skills"]` manifest, through a real pi registers all four skills,
96
+ via `extension:index`.
97
+
98
+ So the row asserts `sourceInfo.source === "extension:index"` on every skill, not
99
+ merely that four skills appeared. The cost is stated plainly: a future release
100
+ that deliberately moved registration to the manifest would FAIL this row until
101
+ the criterion is updated. That is the intended trade — the row's job is to name
102
+ which half is load-bearing, and a row that accepts "some path worked" is exactly
103
+ the check that was missing for four releases. The observed registrar values are
104
+ printed in the witness either way, so a pi-side rename reads as a diagnosable
105
+ mismatch rather than a mystery.
106
+
107
+ ## Outcomes
108
+
109
+ Every row ends in exactly one of four states, and the four partition the
110
+ discovered set — the report asserts the identity
111
+ `discovered = pass + fail + untested + skipped` and says ARITHMETIC MISMATCH if
112
+ it does not hold.
113
+
114
+ The printed arithmetic is `discovered / rows / untested`, and the three words
115
+ mean different things:
116
+
117
+ - **`discovered`** — rows in the matrix above. The denominator.
118
+ - **`rows`** — of those, the ones this run actually DROVE a probe for. A row the
119
+ runner has no probe for is not counted; a BLOCKED run drives none, so `rows`
120
+ reads 0. A SKIPPED row IS counted: its probe ran and decided the row
121
+ unreachable.
122
+ - **`untested`** — rows that produced no witness.
123
+
124
+ - **PASS** — the witness shows the pass criterion.
125
+ - **FAIL(cause)** — the witness shows something else. The cause is the observed
126
+ value, not a category.
127
+ - **UNTESTED(reason)** — no witness was produced. An async row that did not
128
+ reach a terminal state before its polling cap expires **UNTESTED, never PASS**;
129
+ a row with no probe implementation is UNTESTED too, so an unimplemented row is
130
+ arithmetic rather than silence.
131
+ - **SKIPPED(reason)** — the row is unreachable in this run by construction (a
132
+ `git:` install with no ref given, for instance). Reachability is decided in
133
+ planning, not discovered mid-run.
134
+
135
+ **BLOCKED is about the HOST, not the candidate.** The runner probes
136
+ `pi --mode rpc` **before anything is installed**; only a pi that cannot start a
137
+ bare session makes the run BLOCKED, because then nothing about the candidate
138
+ was measured. A candidate that will not pack, will not install, or stops a
139
+ working pi from booting is a **result** — DO-NOT-SHIP — not an untestable
140
+ state. A blocked run is not a failed run and must never be reported as one.
141
+
142
+ **A run that witnessed nothing is INCONCLUSIVE, never ship-with-caveats.** If pi
143
+ booted and no row reached PASS, "no row disagreed" is not evidence; the run gets
144
+ no ship verdict either.
145
+
146
+ Ship line, from the outcomes:
147
+
148
+ | condition | verdict | exit | rows |
149
+ | --- | --- | --- | --- |
150
+ | pi did not boot with NO candidate installed | BLOCKED — no verdict | 3 | 0 |
151
+ | pi booted, the candidate would not install or activate | do not ship, cause named on the verdict | 1 | 0 |
152
+ | any row FAILED | do not ship | 1 | N |
153
+ | pi booted but zero rows PASSED | INCONCLUSIVE — no verdict | 3 | N |
154
+ | any UNTESTED or SKIPPED, at least one PASS | ship with caveats, each named | 2 | N |
155
+ | all PASS | ship | 0 | N |
156
+
157
+ A candidate that never activated leaves **every row UNTESTED, none FAILED, and
158
+ `rows` at 0** — no probe ran, so nothing was witnessed and nothing can honestly
159
+ be called a failure of that row. The activation failure is the verdict's own
160
+ cause. (An earlier revision copied it onto all eleven rows as FAILs and wrote an
161
+ empty evidence dir — a verdict with no witness, against the first hard rule.)
162
+
163
+ **A row is PASS only if its witness has something in it.** A probe that reports
164
+ success and produces no artifact — or an EMPTY one — is recorded UNTESTED, not
165
+ PASS, and the report's excerpt column carries the downgrade reason rather than
166
+ the pass line. The empty case is the reachable one: every probe attaches a
167
+ witness object on its pass path, but `install-selftest` passes on "exit 0 with
168
+ no `[FAIL]` line", which a packaged selftest that printed nothing satisfies
169
+ vacuously, and its witness is that same empty stdout. The check is on CONTENT,
170
+ not on the presence of a file.
171
+
172
+ A usage or self-check error (bad option, unparseable matrix, arithmetic
173
+ mismatch) exits **4**. **Exit 2 is the EXPECTED verdict for a working-tree run**:
174
+ `git-install-loads` is SKIPPED without `--git-ref`. A CI lane should treat 2 as
175
+ a warning and 1/3/4 as failures.
176
+
177
+ ## Deliberately out of scope
178
+
179
+ - **Anything needing a model turn.** Every row above is model-free by
180
+ construction; `get_commands` and the MCP tool calls never reach a provider. A
181
+ row that needs a real LLM turn cannot be a release gate on an unfunded key,
182
+ and a stubbed turn would be a double that mirrors our own assumption
183
+ (AGENTS.md, external contracts).
184
+ - **The `concurrent_session_bind` guard.** Observing it needs a second in-process
185
+ `createAgentSession()`, which needs model config. `docs/subagent-compat.md`
186
+ carries the same TODO; duplicating it here would add a row that can only ever
187
+ be UNTESTED.
188
+ - **Per-language tool and LSP coverage.** `scripts/smoke-tools.mjs` sweeps the
189
+ whole registry nightly. This matrix asserts the packaged path answers at all,
190
+ not that every server answers well.
@@ -6,7 +6,7 @@ server's `initialize` handshake. Generated by `node scripts/server-capabilities.
6
6
  absent on the generating host are listed under *Unavailable* — run in a
7
7
  provisioned environment (the nightly) to capture those rows.
8
8
 
9
- _Last generated: 2026-08-21 on linux; 30 servers captured, 14 unavailable._
9
+ _Last generated: 2026-09-08 on linux; 30 servers captured, 18 unavailable._
10
10
 
11
11
  ## Diagnostic mode + navigation/edit operations
12
12
 
@@ -60,7 +60,7 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
60
60
  - **deno**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, notebookDocumentSync, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
61
61
  - **docker**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, renameProvider, signatureHelpProvider, textDocumentSync
62
62
  - **expert**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, hoverProvider, referencesProvider, textDocumentSync, workspace, workspaceSymbolProvider
63
- - **fsharp**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, inlineValueProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspaceSymbolProvider
63
+ - **fsharp**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspaceSymbolProvider
64
64
  - **gleam**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, referencesProvider, renameProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace
65
65
  - **go**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, typeHierarchyProvider, workspace, workspaceSymbolProvider
66
66
  - **html**: colorProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, linkedEditingRangeProvider, referencesProvider, renameProvider, selectionRangeProvider, signatureHelpProvider, textDocumentSync
@@ -109,12 +109,12 @@ Toolchain/binary not installed here, so capabilities weren't captured
109
109
  (many are the toolchain-gated family tracked in #241):
110
110
 
111
111
  - @prisma/language-server
112
+ - @vue/language-server
112
113
  - PowerShell Editor Services (pwsh Start-EditorServices.ps1 -Stdio)
113
114
  - clangd
114
115
  - cmake-language-server
115
116
  - fish-lsp
116
117
  - haskell-language-server
117
- - intelephense
118
118
  - jdtls
119
119
  - jdtls + lombok javaagent
120
120
  - kotlin-language-server
@@ -122,3 +122,7 @@ Toolchain/binary not installed here, so capabilities weren't captured
122
122
  - ocamllsp
123
123
  - rust-analyzer
124
124
  - sourcekit-lsp
125
+ - typescript native (clean file)
126
+ - typescript native (tsc --lsp --stdio, TS7+)
127
+ - typescript-language-server
128
+ - typescript-language-server (clean file)