@herbertgao/pi-extensions 2026.9.14 → 2026.9.16

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 (206) hide show
  1. package/README.md +8 -3
  2. package/THIRD_PARTY_NOTICES.md +28 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/package.json +1 -1
  4. package/node_modules/@narumitw/pi-btw/dist/index.ts +12 -6
  5. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  6. package/node_modules/@narumitw/pi-btw/package.json +4 -4
  7. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +2 -0
  8. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +16 -4
  9. package/node_modules/pi-jev-auto-mode/CHANGELOG.md +8 -0
  10. package/node_modules/pi-jev-auto-mode/README.md +7 -0
  11. package/node_modules/pi-jev-auto-mode/package.json +1 -1
  12. package/node_modules/pi-jev-auto-mode/src/extension.ts +21 -2
  13. package/node_modules/pi-jev-auto-mode/src/records.ts +68 -2
  14. package/node_modules/pi-jev-auto-mode/src/settings.ts +22 -0
  15. package/node_modules/pi-jev-auto-mode/src/ui.ts +10 -0
  16. package/node_modules/pi-lens/CHANGELOG.md +498 -0
  17. package/node_modules/pi-lens/README.md +45 -2
  18. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +23 -7
  19. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +187 -51
  20. package/node_modules/pi-lens/dist/clients/cache-manager.js +64 -5
  21. package/node_modules/pi-lens/dist/clients/child-unref.js +17 -8
  22. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +2 -0
  23. package/node_modules/pi-lens/dist/clients/config-locations.js +237 -9
  24. package/node_modules/pi-lens/dist/clients/config-resolve.js +7 -1
  25. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +33 -3
  26. package/node_modules/pi-lens/dist/clients/dependency-checker.js +87 -64
  27. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -3
  28. package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +118 -1
  29. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +8 -2
  30. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +23 -4
  31. package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +14 -7
  32. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +26 -28
  33. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +38 -25
  34. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +32 -49
  35. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +16 -14
  36. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +25 -7
  37. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +28 -47
  38. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +11 -4
  39. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +27 -22
  40. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +31 -46
  41. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +29 -46
  42. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +91 -11
  43. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +16 -2
  44. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +38 -23
  45. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +27 -15
  46. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +17 -8
  47. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +31 -21
  48. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +34 -60
  49. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +6 -5
  50. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +12 -5
  51. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
  52. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +22 -6
  53. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +39 -16
  54. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +1 -1
  55. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +27 -18
  56. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +18 -19
  57. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +6 -1
  58. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +6 -2
  59. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +10 -3
  60. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +11 -2
  61. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +10 -2
  62. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +11 -2
  63. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +12 -6
  64. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +30 -15
  65. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +23 -0
  66. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +8 -2
  67. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +11 -1
  68. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +15 -3
  69. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +12 -2
  70. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +27 -39
  71. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +13 -3
  72. package/node_modules/pi-lens/dist/clients/effective-config.js +3 -1
  73. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +42 -11
  74. package/node_modules/pi-lens/dist/clients/formatters.js +49 -11
  75. package/node_modules/pi-lens/dist/clients/git-guard.js +247 -34
  76. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +121 -25
  77. package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +186 -0
  78. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +19 -6
  79. package/node_modules/pi-lens/dist/clients/installer/index.js +281 -32
  80. package/node_modules/pi-lens/dist/clients/jscpd-client.js +8 -0
  81. package/node_modules/pi-lens/dist/clients/latency-logger.js +8 -0
  82. package/node_modules/pi-lens/dist/clients/lens-config.js +66 -8
  83. package/node_modules/pi-lens/dist/clients/lsp/client.js +139 -11
  84. package/node_modules/pi-lens/dist/clients/lsp/config.js +9 -7
  85. package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +41 -0
  86. package/node_modules/pi-lens/dist/clients/lsp/index.js +1 -1
  87. package/node_modules/pi-lens/dist/clients/lsp/launch.js +23 -2
  88. package/node_modules/pi-lens/dist/clients/lsp/server.js +106 -25
  89. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +14 -0
  90. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +105 -16
  91. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +232 -44
  92. package/node_modules/pi-lens/dist/clients/mcp/review.js +53 -7
  93. package/node_modules/pi-lens/dist/clients/opengrep-client.js +11 -6
  94. package/node_modules/pi-lens/dist/clients/pipeline.js +121 -66
  95. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +21 -3
  96. package/node_modules/pi-lens/dist/clients/project-lens-config.js +11 -3
  97. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +34 -26
  98. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +16 -10
  99. package/node_modules/pi-lens/dist/clients/ruff-client.js +31 -4
  100. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +38 -4
  101. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +16 -5
  102. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +27 -12
  103. package/node_modules/pi-lens/dist/clients/runtime-turn.js +447 -280
  104. package/node_modules/pi-lens/dist/clients/safe-spawn.js +256 -65
  105. package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +84 -1
  106. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +119 -58
  107. package/node_modules/pi-lens/dist/clients/turn-end/lane.js +51 -0
  108. package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +112 -0
  109. package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +204 -0
  110. package/node_modules/pi-lens/dist/clients/warm-attach.js +59 -0
  111. package/node_modules/pi-lens/dist/clients/widget-state.js +145 -14
  112. package/node_modules/pi-lens/dist/clients/workspace-topology.js +57 -3
  113. package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -13
  114. package/node_modules/pi-lens/dist/index.js +5695 -3733
  115. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +4 -0
  116. package/node_modules/pi-lens/dist/mcp/server.js +33 -21
  117. package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +123 -0
  118. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +43 -16
  119. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +118 -7
  120. package/node_modules/pi-lens/docs/adr/0001-stale-advisory-live-arm.md +29 -0
  121. package/node_modules/pi-lens/docs/adr/0002-workspace-hash-rendezvous.md +30 -0
  122. package/node_modules/pi-lens/docs/adr/0003-git-guard-latch-writer.md +203 -0
  123. package/node_modules/pi-lens/docs/adr/0004-disposition-policy-seam.md +38 -0
  124. package/node_modules/pi-lens/docs/adr/0005-tool-availability-enforcement-seam.md +29 -0
  125. package/node_modules/pi-lens/docs/adr/0006-derived-state-benchmark-first.md +31 -0
  126. package/node_modules/pi-lens/docs/adr/0007-end-to-end-witness-per-seam-slice.md +38 -0
  127. package/node_modules/pi-lens/docs/adr/0008-turn-end-lane-interface.md +165 -0
  128. package/node_modules/pi-lens/docs/adr/0009-reported-path-attribution.md +114 -0
  129. package/node_modules/pi-lens/docs/adr/README.md +26 -0
  130. package/node_modules/pi-lens/docs/agent-tools.md +18 -1
  131. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +4 -3
  132. package/node_modules/pi-lens/docs/configuration.md +55 -1
  133. package/node_modules/pi-lens/docs/engineering-principles.md +202 -0
  134. package/node_modules/pi-lens/docs/environment-variables.md +61 -4
  135. package/node_modules/pi-lens/docs/features.md +2 -2
  136. package/node_modules/pi-lens/docs/globalconfig.md +6 -1
  137. package/node_modules/pi-lens/docs/language-coverage.md +17 -0
  138. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +98 -31
  139. package/node_modules/pi-lens/docs/pi-lens-fixer.md +57 -3
  140. package/node_modules/pi-lens/docs/pi-lens-investigator.md +9 -0
  141. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +16 -0
  142. package/node_modules/pi-lens/docs/pi-lens-subagent.md +9 -0
  143. package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
  144. package/node_modules/pi-lens/docs/release-qa-baseline.md +2 -0
  145. package/node_modules/pi-lens/docs/servercapabilities.md +21 -11
  146. package/node_modules/pi-lens/docs/settings.md +12 -3
  147. package/node_modules/pi-lens/docs/subagent-compat.md +1 -1
  148. package/node_modules/pi-lens/package.json +5 -3
  149. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
  150. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +26 -0
  151. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +10 -0
  152. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/unchecked-numeric-parse-python-test.yml +18 -0
  153. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +4 -3
  154. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +2 -2
  155. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-assert-tuple.yml +23 -13
  156. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-boolean-in-except.yml +7 -3
  157. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-console-except-error-js.yml +2 -2
  158. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-console-except-error.yml +2 -2
  159. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +12 -7
  160. package/node_modules/pi-lens/rules/ast-grep-rules/rules/unchecked-numeric-parse-python.yml +44 -0
  161. package/node_modules/pi-lens/rules/ast-grep-rules/rules/unchecked-throwing-call-python.yml +5 -3
  162. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/console-statement.yml +2 -2
  163. package/node_modules/pi-lens/scripts/install-selftest.mjs +21 -17
  164. package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +123 -0
  165. package/node_modules/pi-mcp-adapter/CHANGELOG.md +29 -0
  166. package/node_modules/pi-mcp-adapter/OAUTH.md +369 -0
  167. package/node_modules/pi-mcp-adapter/README.md +12 -5
  168. package/node_modules/pi-mcp-adapter/config.ts +31 -8
  169. package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +1 -1
  170. package/node_modules/pi-mcp-adapter/dist/config.js +33 -8
  171. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
  172. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +15 -2
  173. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +1 -1
  174. package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +2 -0
  175. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +27 -2
  176. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +1 -1
  177. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +1 -1
  178. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -1
  179. package/node_modules/pi-mcp-adapter/dist/server-manager.js +6 -4
  180. package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +1 -1
  181. package/node_modules/pi-mcp-adapter/dist/types.d.ts +2 -2
  182. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +2 -0
  183. package/node_modules/pi-mcp-adapter/dist/utils.js +10 -3
  184. package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -1
  185. package/node_modules/pi-mcp-adapter/index.ts +37 -20
  186. package/node_modules/pi-mcp-adapter/init.ts +14 -15
  187. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +16 -2
  188. package/node_modules/pi-mcp-adapter/mcp-auth.ts +27 -2
  189. package/node_modules/pi-mcp-adapter/metadata-cache.ts +1 -1
  190. package/node_modules/pi-mcp-adapter/package.json +3 -2
  191. package/node_modules/pi-mcp-adapter/proxy-modes.ts +1 -1
  192. package/node_modules/pi-mcp-adapter/server-manager.ts +6 -3
  193. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +99 -6
  194. package/node_modules/pi-mcp-adapter/types.ts +2 -2
  195. package/node_modules/pi-mcp-adapter/ui-session.ts +60 -27
  196. package/node_modules/pi-mcp-adapter/utils.ts +11 -3
  197. package/node_modules/pi-multi-account/CHANGELOG.md +6 -0
  198. package/node_modules/pi-multi-account/README.md +15 -1
  199. package/node_modules/pi-multi-account/index.ts +295 -41
  200. package/node_modules/pi-multi-account/package.json +1 -1
  201. package/node_modules/pi-next-cue/.github/workflows/publish.yml +20 -0
  202. package/node_modules/pi-next-cue/LICENSE +21 -0
  203. package/node_modules/pi-next-cue/README.md +81 -0
  204. package/node_modules/pi-next-cue/index.ts +358 -0
  205. package/node_modules/pi-next-cue/package.json +28 -0
  206. package/package.json +10 -7
@@ -9,7 +9,8 @@ confirmed against Neovim's LSP client, which sidesteps this entirely by being as
9
9
 
10
10
  Generate/refresh this matrix with `node scripts/characterize-lsp.mjs [--install]`
11
11
  (the `mode` column) and `node scripts/probe-clean-signal.mjs [--install]` (the
12
- `clean-behavior` column — 4-way: 2 / 2* / 3 / unknown). Both **merge** in place: a server the
12
+ `clean-behavior` column — 4-way: 2 / 2* / 3 / unknown — and the `first-publish`
13
+ column, #3310). Both **merge** in place: a server the
13
14
  running host couldn't spawn keeps its prior row, so an ubuntu-poor run can't
14
15
  regress a richer one (#390). The nightly **tool-smoke** workflow runs both (plus
15
16
  `server-capabilities.mjs`) and opens/updates a single auto-PR
@@ -27,6 +28,49 @@ anything). The native TS7 launch variant (`typescript7`/`typescript7-clean`,
27
28
  #524/#526) is deliberately excluded from comparison against classic's marker —
28
29
  they share a server id but not a verified clean-signal behavior.
29
30
 
31
+ What IS gated is the pair of COMMITTED sources:
32
+ `tests/config/lsp-clean-behavior-census.test.ts` (#3347) compares the
33
+ `clean-behavior` column below against the `silentOnClean` markers in both
34
+ directions — every measured push row against its marker, and every marker
35
+ against a push row measured `silent` — so a nightly refresh cannot merge a
36
+ re-measured server until its marker moves with it, and a marker cannot outlive
37
+ the measurement that justified it. Push rows the probe has not classified are
38
+ admitted by name in that file, and an admission reds once its row becomes
39
+ measured.
40
+
41
+ ## First publish: is the first push an answer? (#3310)
42
+
43
+ A second, ORTHOGONAL axis to the tiers below, measured from the same probe run
44
+ and written as the `first-publish` column:
45
+
46
+ | value | meaning | wait policy |
47
+ |---|---|---|
48
+ | `direct` | the first publish for a dirty file carries the findings | the first publish resolves the wait, as it always did |
49
+ | `empty-first` | the server answers `didOpen` with an EMPTY set while a one-time index builds, then publishes again once indexing ends | the client HOLDS that first empty publish (`emptyFirstPublish: "indexing"` in `clients/lsp/wait-policy/strategies.ts`); the server's own next publish releases it, and the hold is one-shot per client session |
50
+ | `empty-only` | every publish on the dirty fixture was empty | not classifiable on this axis — an undiagnosed dirty fixture looks exactly like an unfinished index, so nothing is inferred in either direction |
51
+ | `n/a (pull)` / `TBD` | pull-mode, or not measured on a host that could reach the server | no behavior change |
52
+
53
+ Why this axis had to exist at all: the wait needs a positive signal, and an
54
+ empty publish is a positive signal for a Tier 2/2\* server (a genuinely clean
55
+ file) and a MEANINGLESS one for a server that has not finished indexing. The two
56
+ are identical on the wire, so the difference is a measurement, not an inference.
57
+ intelephense is the measured member (2026-09-23, v1.18.5): `[]` at +295ms,
58
+ `indexingStarted` at +301ms — i.e. AFTER the empty publish, so no
59
+ work-in-progress signal is available at the moment the decision must be made —
60
+ `indexingEnded` at +689ms and the real 2-diagnostic set at +696ms. On a
61
+ genuinely clean file the same session publishes `[]` twice (at +304ms and again
62
+ at +663ms, right after indexing), which is what lets the held publish be
63
+ released by the server itself rather than by a timer; a WARM touch publishes the
64
+ real set first, so the hold costs nothing once the session is warm. pi-lens does
65
+ not advertise `window.workDoneProgress` (#974: advertising it crash-loops
66
+ opengrep's `--experimental` LSP mode), so `$/progress` is not an available
67
+ discriminator either.
68
+
69
+ `tests/config/lsp-first-publish-census.test.ts` compares this column against the
70
+ `emptyFirstPublish` markers and reds in BOTH directions, which is the expiry
71
+ check: when the nightly re-measures a server into a different class, the docs
72
+ refresh cannot merge until the marker is updated with it.
73
+
30
74
  ## The strategies
31
75
 
32
76
  | Tier | Signal | Affirmative clean? | Example |
@@ -48,7 +92,7 @@ the next touch probes again. Only silence through the full push budget latches
48
92
  that server id as navigation-only for the service session. A publish upgrades it
49
93
  to the ordinary push-wait policy.
50
94
 
51
- ## Matrix (dev box + CI nightly; mode last refreshed 2026-06-17 from run 27713958681, clean-behavior probed on the dev box 2026-07-08 — #460)
95
+ ## Matrix (dev box + CI nightly; mode last refreshed 2026-06-17 from run 27713958681, clean-behavior probed in run 35914033696 — #460)
52
96
 
53
97
  `mode` from cached capabilities; `clean-behavior` from the phase-aware publish-trace
54
98
  probe. The probe attributes publishes to two phases — the **dirty touch** (proves the
@@ -63,37 +107,49 @@ nightly steps, **dev** = the dev box (a row measured on both reads `dev+ci`).
63
107
  Merges never blank a prior good value, so a CI non-result leaves the dev
64
108
  classification standing.
65
109
 
66
- | lang | server | mode | clean-behavior | tier | src |
67
- |---|---|---|---|---|---|
68
- | json | vscode-json-language-server | pull | — | 1 | dev+ci |
69
- | css | vscode-css-language-server | pull | — | 1 | dev+ci |
70
- | html | vscode-html-language-server | pull | — | 1 | dev+ci |
71
- | rust | rust-analyzer | pull | — | 1 | dev |
72
- | svelte | svelte-language-server | pull | — | 1 | dev+ci |
73
- | deno | deno (alt of typescript) | pull | — | 1 | dev+ci |
74
- | ruby | ruby-lsp | pull | — | 1 | ci |
75
- | csharp | csharp-ls | pull | — | 1 | ci |
76
- | typescript | typescript-language-server | push-only | silent | 3 | dev+ci |
77
- | python | pyright | push-only | publishes-versioned | 2 | dev+ci |
78
- | jedi | jedi-language-server (alt of python) | push-only | publishes-versioned | 2 | ci |
79
- | yaml | yaml-language-server | push-only | publishes-unversioned | 2* | dev+ci |
80
- | shell | bash-language-server | push-only | publishes-versioned | 2 | dev+ci |
81
- | dockerfile | docker-langserver | push-only | publishes-unversioned | 2* | dev+ci |
82
- | toml | taplo | push-only | publishes-unversioned | 2* | dev+ci |
83
- | terraform | terraform-ls | push-only | TBD | 2/3? | dev+ci |
84
- | prisma | @prisma/language-server | push-only | publishes-unversioned | 2* | dev+ci |
85
- | php | intelephense | push-only | TBD | 2/3? | dev+ci |
86
- | zig | zls | push-only | publishes-unversioned | 2* | dev+ci |
87
- | vue | @vue/language-server | push-only | TBD | 2/3? | dev+ci |
88
- | dart | dart language-server | push-only | publishes-unversioned | 2* | ci |
89
- | gleam | gleam lsp | push-only | publishes-unversioned | 2* | ci |
90
- | clojure | clojure-lsp | push-only | publishes-unversioned | 2* | ci |
91
- | opengrep | opengrep (aux) | push-only | publishes-unversioned | 2* | dev+ci |
92
- | ast-grep | ast-grep (aux) | push-only | publishes-versioned | 2 | dev+ci |
110
+ `vue`'s `clean-behavior` was hand-reset to `unknown` (#3390): its
111
+ `publishes-unversioned` cell came from 58/45 publishes that the shared
112
+ `extension.log` window had attributed to vue but that belonged to `tinymist`.
113
+ With the sink scoped per server, nightly 36046209160 measured vue 0/0, and an
114
+ `unknown` result is never written by the merge above — so the refuted value had
115
+ to be cleared by hand. It stays `unknown` until a run observes
116
+ `@vue/language-server` publish; `tests/config/lsp-clean-behavior-census.test.ts`
117
+ carries the named admission until then.
118
+
119
+ | lang | server | mode | clean-behavior | first-publish | tier | src |
120
+ |---|---|---|---|---|---|---|
121
+ | json | vscode-json-language-server | pull | — | n/a (pull) | 1 | dev+ci |
122
+ | css | vscode-css-language-server | pull | — | n/a (pull) | 1 | dev+ci |
123
+ | html | vscode-html-language-server | pull | — | n/a (pull) | 1 | dev+ci |
124
+ | rust | rust-analyzer | pull | — | n/a (pull) | 1 | dev |
125
+ | svelte | svelte-language-server | pull | — | n/a (pull) | 1 | dev+ci |
126
+ | deno | deno (alt of typescript) | pull | — | n/a (pull) | 1 | dev+ci |
127
+ | ruby | ruby-lsp | pull | — | n/a (pull) | 1 | ci |
128
+ | csharp | csharp-ls | pull | — | n/a (pull) | 1 | ci |
129
+ | typescript | typescript-language-server | push-only | silent | direct | 3 | dev+ci |
130
+ | markdown | marksman | push-only | silent | direct | 3 | ci |
131
+ | lua | lua-language-server | push-only | silent | direct | 3 | dev+ci |
132
+ | python | pyright | push-only | publishes-versioned | direct | 2 | dev+ci |
133
+ | jedi | jedi-language-server (alt of python) | push-only | publishes-versioned | direct | 2 | ci |
134
+ | yaml | yaml-language-server | push-only | publishes-unversioned | direct | 2* | dev+ci |
135
+ | shell | bash-language-server | push-only | publishes-versioned | direct | 2 | dev+ci |
136
+ | dockerfile | docker-langserver | push-only | publishes-unversioned | direct | 2* | dev+ci |
137
+ | toml | taplo | push-only | publishes-unversioned | direct | 2* | dev+ci |
138
+ | terraform | terraform-ls | push-only | TBD | TBD | 2/3? | dev+ci |
139
+ | prisma | @prisma/language-server | push-only | publishes-unversioned | direct | 2* | dev+ci |
140
+ | php | intelephense | push-only | publishes-unversioned | empty-first | 2* | dev+ci |
141
+ | zig | zls | push-only | publishes-unversioned | direct | 2* | dev+ci |
142
+ | vue | @vue/language-server | push-only | unknown | direct | 2/3? | dev+ci |
143
+ | dart | dart language-server | push-only | publishes-unversioned | direct | 2* | ci |
144
+ | gleam | gleam lsp | push-only | publishes-unversioned | direct | 2* | ci |
145
+ | clojure | clojure-lsp | push-only | publishes-unversioned | direct | 2* | ci |
146
+ | opengrep | opengrep (aux) | push-only | publishes-unversioned | direct | 2* | dev+ci |
147
+ | ast-grep | ast-grep (aux) | push-only | publishes-versioned | direct | 2 | dev+ci |
148
+ | cue | CUE Language Server (cue lsp serve) | push-only | publishes-versioned | direct | 2 | dev+ci |
93
149
 
94
150
  **Unknown — fixture exists, mode not yet captured.** The toolchain-gated family
95
151
  (no auto-install today; tracked in #241) — `go` (gopls), `java` (jdtls),
96
- `kotlin`, `swift` (sourcekit-lsp), `lua`, `cpp` (clangd), `haskell`, `elixir`,
152
+ `kotlin`, `swift` (sourcekit-lsp), `cpp` (clangd), `haskell`, `elixir`,
97
153
  `ocaml`, `nix` (nixd), `fsharp`. Their servers don't install in the nightly, so
98
154
  characterize reports `unknown` (a non-failure ⚠). Once #241 lands they'll fill in
99
155
  the same way clojure-lsp/gleam now do (both auto-install via the github strategy
@@ -103,7 +159,8 @@ and were characterized `push-only` in the run above).
103
159
  - **Mode ≠ tier, and the split needs BOTH axes.** Push-only further splits along
104
160
  latency (does anything publish on a clean transition? — silence is the only
105
161
  budget-wait case, because pi-lens's publish handler emits and early-returns the
106
- wait on EVERY publish, versioned or not) and currency-proof (is the publish
162
+ wait on every publish, versioned or not, with the single #3310 exception of a
163
+ held empty FIRST publish from an `empty-first` server) and currency-proof (is the publish
107
164
  versioned, i.e. provably about the live edit?). The 4-way
108
165
  `probe-clean-signal.mjs` measurement drives this: ast-grep → 2, yaml/opengrep →
109
166
  2\*, typescript (clean file) → 3.
@@ -121,6 +178,16 @@ and were characterized `push-only` in the run above).
121
178
  fixtures for exactly this reason. Corollary: a 2\* measured only on a dirty
122
179
  fixture may overstate a server whose publishes stop when its set goes empty —
123
180
  langs without a clean fixture carry that caveat.
181
+ - **The probe's publish capture was dead, and the column looked alive anyway
182
+ (#3310).** `probe-clean-signal.mjs` intercepted `console.error` for the
183
+ `[lsp-pub]` trace, but #1333 moved that trace's sink to `extension.log` — so
184
+ every phase counted zero publishes, every server classified `unknown`, and the
185
+ #390 merge guard then preserved the July 2026 values verbatim. A dead
186
+ instrument and a healthy one are indistinguishable when non-results are
187
+ discarded by design. The probe now reads the sink the client actually writes;
188
+ `first-publish` measurements on the dev box, 2026-09-23: php `empty-first`,
189
+ typescript / opengrep / ast-grep / marksman `direct` (so the class does not
190
+ extend to them on the measurement, whatever their comments suggest).
124
191
  - **#458's learned-deadline target set = the tier-3 rows only.** 2\* rows resolve
125
192
  the wait at runtime and must NOT be given learned deadlines.
126
193
  - **Tier 3 is budget-bound by necessity**, not laziness: a silent server's silence is
@@ -9,8 +9,48 @@
9
9
  - Preserve contributor authorship and leave Git authority to the orchestrator
10
10
  unless the delegation grants it explicitly.
11
11
 
12
+ ## Standing procedure
13
+
14
+ ### Standard mechanics
15
+
16
+ - Commit the code as soon as the targeted suite is green, then add evidence in
17
+ a later commit. A worker can be settled mid-evidence-pass; on PR #3268 the
18
+ orchestrator had to commit the tree.
19
+ - A whole-module `vi.mock` of a production module must spread `importOriginal`.
20
+ Run `tests/config/vi-mock-export-sweep.test.ts`.
21
+ - Exact-pin sweeps and merge state: `tests/config/glossary-synonym-sweep.test.ts`
22
+ (#3279) pins the live retired-synonym identifier population per (term, file)
23
+ exactly, in both directions. If a change adds or removes one of the pinned
24
+ identifier uses, run the sweep on the head and on the merge of
25
+ `origin/master` + head before pushing, then re-pin in the same PR using the
26
+ sweep's own `UNPINNED`/`STALE` output. On 2026-09-23, two green PRs merged
27
+ red (#3279's pins predated #3283, leaving master red until #3288), and #3284
28
+ was red on its own `path` count changes (cue-vet 5→6, dart-analyze 6→4)
29
+ until an orchestrator trailing commit re-pinned.
30
+
31
+ ### Failure list before code
32
+
33
+ Before the first edit of any fix, write the list of ways the change could fail
34
+ (the directions the mutation table will later prove) in the PR body. The
35
+ mutation table is that list with transcripts, never a list invented after the
36
+ code. This week's evidence: #3252 r1 shipped an exit table whose inverse
37
+ direction (nonzero WITH findings) was never listed and was caught by the
38
+ reviewer.
39
+
40
+ Seams are named in the brief before the round; no test is written at an
41
+ unconfirmed seam — a fixer that needs a new seam stops and reports it as a
42
+ finding, not as a test.
43
+
44
+ A fix round does not deepen: no refactor, no helper extraction, no rename
45
+ beyond the fix's own lines; deepening is its own slice under the owning
46
+ umbrella. #3254 and #3256 stayed inside their briefs; #3178's four rounds show
47
+ the cost of not doing so.
48
+
12
49
  ## Evidence
13
50
 
51
+ - Witness rule (ADR 0007): #1605 owns the witness lanes, and their fixtures
52
+ live under `tests/fixtures/witness/<slice>/`.
53
+
14
54
  - Add a regression test through the production path.
15
55
  - Capture the pre-fix assertion failure.
16
56
  - Prove the fixed test passes.
@@ -47,9 +87,23 @@
47
87
 
48
88
  - Without Git authority, leave changes uncommitted.
49
89
  - Write root-level `PR_BODY.md` and `COMMIT_MSG.txt`; keep both untracked.
50
- - PR body headings: `## Summary`, `## Tests`, `## Blast radius`,
51
- `## Class sweep`, `## Observability`, and `## Test assessment` when tests
52
- changed.
90
+ - The PR body is the whole `.github/PULL_REQUEST_TEMPLATE.md`, every
91
+ heading present in order: `## Why` (one sentence), `## Notes for the
92
+ reviewer`, `## Change outline`, `## Summary`, `## Type of change`,
93
+ `## Area`, `## Checklist`, `## Tests`, `## Blast radius`,
94
+ `## Observability` (a record literal from the runtime diff, or exactly
95
+ `No new failure path; no record added.`), `## Class sweep`, and
96
+ `## Test assessment`. A brief that names only some headings does not
97
+ shorten this list.
98
+ - Run `node scripts/check-pr-body.mjs --lint-local PR_BODY.md` and
99
+ `node scripts/check-changelog-fragments.mjs` before the hand-back; both
100
+ must pass, and the hand-back quotes them. A changelog fragment is
101
+ `---` / `section: <Added|Changed|Deprecated|Removed|Fixed|Security>` /
102
+ `---` / blank / one `- ` bullet. (Four of six Luna PRs on 2026-09-23
103
+ redded the PR-body and changelog gates on the first head; the fixes were
104
+ all mechanical.)
105
+ - The hand-back carries the commit SHA; a dirty tree is an incomplete
106
+ round.
53
107
  - Include every red, mutation result, skipped check, and environment block.
54
108
  - Answer each finding id with `fixed`, `not fixed`, or `withdrawn (reason)`.
55
109
  - Report verdict, changed files, totals, and unverifiable checks.
@@ -26,6 +26,15 @@
26
26
 
27
27
  ## Evidence rules
28
28
 
29
+ - **Already-shipped check before naming a slice:** for every umbrella member the
30
+ brief cites as remaining work, grep the current tree and the closing PRs and
31
+ state shipped, partially shipped, or not shipped with `file:line`; a first
32
+ slice may name only work whose absence was verified on the current head.
33
+ The 2026-09-22 primitives brief named three scanner filter blocks as the
34
+ #1461 first slice even though #1622/#1625/#1628 had already removed them;
35
+ the fixer found the premise error in PR #3264 and the #1892 comment on
36
+ 2026-09-23.
37
+
29
38
  - A reported defect is not confirmed until the production-path probe is red on
30
39
  the current tree for the reported reason.
31
40
  - A probe must distinguish competing hypotheses, use independent observations,
@@ -8,9 +8,25 @@
8
8
  - Reproduce the claimed behavior through the production entry point.
9
9
  - Report only proven findings; do not repair the author's branch.
10
10
 
11
+ ## Standard mechanics
12
+
13
+ - Write `REVIEW.md` as a file at the worktree root, not only in the final
14
+ answer. Two verifies this week (PR #3261 r3 and PR #3264 r3) delivered the
15
+ review only in the answer text.
16
+ - When the fixer settled before its evidence pass, run the mutation table
17
+ yourself and say so.
18
+
11
19
  ## Verification
12
20
 
13
21
  - Use `git diff origin/master...HEAD` or the merge-base equivalent.
22
+ - For any change involving the pinned retired-synonym identifier population,
23
+ run the exact-pin sweeps on the MERGE of `origin/master` + head, not only on
24
+ the head. `tests/config/glossary-synonym-sweep.test.ts` (#3279) asserts the
25
+ live (term, file) population exactly in both directions; require same-PR
26
+ re-pinning from its `UNPINNED`/`STALE` output. The 2026-09-23 evidence is
27
+ two green PRs merging red (#3279's pins predated #3283, fixed on master by
28
+ #3288), plus #3284's own `path` count red (cue-vet 5→6, dart-analyze 6→4)
29
+ until a trailing re-pin.
14
30
  - Build and run the targeted and required governance suites.
15
31
  - Revert or neuter the source fix and verify the red-first test fails.
16
32
  - Mutate every new guard, filter, cap, fallback, and lifecycle path.
@@ -51,6 +51,15 @@ runner's own notes say which mode lifts it). Run Vitest as
51
51
  tree-sitter grammar prefetch hangs offline, verify through direct probes of the
52
52
  built code and say so; the orchestrator re-runs the files outside the sandbox.
53
53
 
54
+ Every Vitest invocation on the maintainer host exports
55
+ `PI_LENS_TEST_MAX_WORKERS=6` and names its files; never the full suite. The
56
+ plegma daemon's cgroup holds every worker's child processes, and on 2026-09-19
57
+ one fixer's fan-out (16 forks on a 32-core host plus the real language servers
58
+ its probes spawned) took the unit to 64 GB, systemd-oomd killed the daemon, and
59
+ every live worker died with it. Kill every language server a probe spawns
60
+ before moving on; the previous worker's unkilled servers were part of that
61
+ footprint.
62
+
54
63
  When Git authority is granted, use one logical commit with an imperative,
55
64
  conventional-prefix subject of at most 50 characters, a blank line, and a
56
65
  72-column body that states what and why. Reference the issue. Open a PR, do not
@@ -108,6 +108,7 @@ this policy explicitly reserves the right to change.
108
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
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
110
  | `PILENS_CFG_0009` | A tool config key is unknown or names a required, non-disableable tool. | The shared model-facing tool registry (`clients/tool-config.ts`) and both pi/MCP registration surfaces. |
111
+ | `PILENS_CFG_0010` | A lower-precedence supported global config file exists but was shadowed by the winning file. | `reportGlobalConfigShadowing` (`clients/lens-config.ts`), recorded once through `recordDegradationOnce`. |
111
112
 
112
113
  A reserved code is registered and referenced by the deprecation registry, but
113
114
  nothing emits it today. That is deliberate: the number must be pinned before the
@@ -85,6 +85,8 @@ PR's packed tarball (#2700, the check #2587 was missing). `attw`
85
85
  | 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 |
86
86
  | 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 | — |
87
87
  | 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 |
88
+ | global-config-location | the agent-dir global config file supplies the global tier when it exists and the legacy default does not | mcp-stdio | `tools/call` `pilens_effective_config` on a real pi-lens MCP server whose env sets `PI_CODING_AGENT_DIR` at a scratch dir holding `extensions/pi-lens.json` | the tool result NAMES the agent-dir file as a contributing config document (the `pi-coding-agent-dir` winner) | tool result text | `tests/clients/global-config-location.test.ts` covers the resolution in-process; no smoke drives the packaged MCP path with the env set | — |
89
+ | config-shadow-record | a lower-precedence global config file beside the winner is recorded once per session | mcp-stdio | `tools/call` `pilens_effective_config` then `pilens_health` twice, on a real MCP server whose env has BOTH `~/.pi-lens/config.json` and `PI_CODING_AGENT_DIR/extensions/pi-lens.json` present | health carries a `config-location-shadowed: 1` line naming the shadowed agent-dir file, and the count stays 1 on a second health read after a further config load | the two health tool result texts | `clients/degradation-ledger.ts` `recordDegradationOnce` and `tests/clients/global-config-location.test.ts`; no smoke asserts the record end to end | #1605 lane 2 (availability-lifecycle): the degradation-recorded half, as `degradation-visible`; this row additionally pins the once-per-session count across two loads |
88
90
  | 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 | — |
89
91
  | publish-toolchain-pinned | the RELEASE WORKFLOW's publish job runs the npm it pins, and that npm validates the tarball | npm-pack | `npx -y "npm@<packageManager pin>" --version` then `npx -y "npm@<packageManager pin>" publish --dry-run`, both in the scratch export | the pinned invocation reports the pin version AND the dry run exits 0, or npm reports the version is already published after packing; a pinned invocation resolution or registry failure leaves the row UNMEASURED | the two commands with their output | new — `tests/config/release-npm-pin-gate.test.ts` pins release.yml's TEXT; this row is the only thing that RUNS the publish job's toolchain before a tag exists (#2940) | — |
90
92
  | tool-smoke-install | every npm/pip entry in the installer registry resolves on a real install | npm-install | `node <export>/scripts/smoke-tools.mjs --install --install-registry --installer-root=<installed>/` (registry `<installed>/dist/clients/installer/index.js`; about 1m 29s cold on this box for 33 entries; harness from export root) | the report shows every npm/pip entry resolved or a named legitimate skip (toolchain absent, declined), and no genuine install failure; a registry-unreachable classification leaves the lane UNMEASURED; requires network access to the npm and pip registries | install-registry JSON report | `classifyInstallOutcome` from the #2661 fixture lanes — this lane sweeps the whole npm/pip registry, where fixture lanes exercise only the entries their fixtures name | — |
@@ -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-09-09 on linux; 31 servers captured, 13 unavailable._
9
+ _Last generated: 2026-09-23 on linux; 37 servers captured, 9 unavailable._
10
10
 
11
11
  ## Diagnostic mode + navigation/edit operations
12
12
 
@@ -17,13 +17,16 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
17
17
  | ast-grep | push-only | · | · | · | · | · | ✓ | · | · | · | ✓ | · | · | · | 1 |
18
18
  | bash | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
19
19
  | clojure | push-only | · | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 62 |
20
+ | cpp | push-only | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 3 |
20
21
  | csharp | pull | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
21
22
  | css | pull | · | ✓ | · | · | ✓ | ✓ | · | ✓ | · | ✓ | ✓ | · | · | 0 |
22
23
  | cue | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | · | ✓ | ✓ | · | · | 1 |
23
24
  | dart | push-only | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 18 |
24
25
  | deno | pull | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 2 |
25
26
  | docker | push-only | · | ✓ | · | · | · | ✓ | ✓ | ✓ | · | · | ✓ | · | · | 0 |
27
+ | emmylua | pull | · | ✓ | · | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | · | · | · | 4 |
26
28
  | expert | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | · | · | · | 2 |
29
+ | fish | push-only | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | 22 |
27
30
  | fsharp | push-only | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
28
31
  | gleam | push-only | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · | · | 0 |
29
32
  | go | push-only | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 47 |
@@ -33,13 +36,15 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
33
36
  | marksman | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
34
37
  | opengrep | push-only | · | · | · | · | · | ✓ | · | · | · | ✓ | · | · | · | 2 |
35
38
  | php | push-only | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | · | 0 |
36
- | prisma | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | · | · | ✓ | · | · | 0 |
39
+ | powershell | push-only | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
40
+ | prisma | push-only | · | ✓ | · | · | ✓ | ✓ | · | ✓ | · | ✓ | ✓ | · | · | 0 |
37
41
  | python | push-only | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | 0 |
38
42
  | python-jedi | push-only | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
39
43
  | ruby | pull | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
40
44
  | rust | pull | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
41
45
  | svelte | pull | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
42
46
  | terraform | push-only | · | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | 7 |
47
+ | tinymist | push-only | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | 29 |
43
48
  | toml | push-only | · | · | · | · | · | ✓ | · | ✓ | · | · | ✓ | · | · | 0 |
44
49
  | typescript | push-only | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | 8 |
45
50
  | typos | push-only | · | · | · | · | · | · | · | · | · | ✓ | · | · | · | 1 |
@@ -53,13 +58,16 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
53
58
  - **ast-grep**: codeActionProvider, executeCommandProvider, hoverProvider, textDocumentSync
54
59
  - **bash**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, hoverProvider, referencesProvider, renameProvider, textDocumentSync, workspaceSymbolProvider
55
60
  - **clojure**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, linkedEditingRangeProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
61
+ - **cpp**: astProvider, callHierarchyProvider, clangdInlayHintsProvider, codeActionProvider, compilationDatabase, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, foldingRangeProvider, hoverProvider, implementationProvider, inactiveRegionsProvider, inlayHintProvider, memoryUsageProvider, positionEncoding, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, standardTypeHierarchyProvider, textDocumentSync, typeDefinitionProvider, typeHierarchyProvider, workspaceSymbolProvider
56
62
  - **csharp**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, referencesProvider, renameProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, typeHierarchyProvider, workspace, workspaceSymbolProvider
57
63
  - **css**: codeActionProvider, colorProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, referencesProvider, renameProvider, selectionRangeProvider, textDocumentSync
58
64
  - **cue**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentSymbolProvider, executeCommandProvider, hoverProvider, referencesProvider, renameProvider, textDocumentSync, workspace
59
65
  - **dart**: callHierarchyProvider, codeActionProvider, codeLensProvider, colorProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, inlineValueProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, typeHierarchyProvider, workspace, workspaceSymbolProvider
60
66
  - **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
67
  - **docker**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, renameProvider, signatureHelpProvider, textDocumentSync
68
+ - **emmylua**: codeActionProvider, definitionProvider, diagnosticProvider, documentSymbolProvider, executeCommandProvider, hoverProvider, referencesProvider, textDocumentSync, workspaceSymbolProvider
62
69
  - **expert**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, hoverProvider, referencesProvider, textDocumentSync, workspace, workspaceSymbolProvider
70
+ - **fish**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
63
71
  - **fsharp**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspaceSymbolProvider
64
72
  - **gleam**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, referencesProvider, renameProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace
65
73
  - **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
@@ -69,13 +77,15 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
69
77
  - **marksman**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentSymbolProvider, executeCommandProvider, hoverProvider, referencesProvider, renameProvider, semanticTokensProvider, textDocumentSync, workspace, workspaceSymbolProvider
70
78
  - **opengrep**: codeActionProvider, executeCommandProvider, hoverProvider, textDocumentSync, workspace
71
79
  - **php**: codeActionProvider, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlineValueProvider, referencesProvider, renameProvider, selectionRangeProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, typeHierarchyProvider, workspace, workspaceSymbolProvider
72
- - **prisma**: completionProvider, definitionProvider, documentFormattingProvider, documentSymbolProvider, hoverProvider, referencesProvider, renameProvider, textDocumentSync
80
+ - **powershell**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, experimental, foldingRangeProvider, hoverProvider, referencesProvider, renameProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
81
+ - **prisma**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentSymbolProvider, hoverProvider, referencesProvider, renameProvider, textDocumentSync
73
82
  - **python**: callHierarchyProvider, codeActionProvider, completionProvider, declarationProvider, definitionProvider, documentHighlightProvider, documentSymbolProvider, executeCommandProvider, hoverProvider, referencesProvider, renameProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
74
83
  - **python-jedi**: codeActionProvider, completionProvider, declarationProvider, definitionProvider, documentHighlightProvider, documentSymbolProvider, executeCommandProvider, hoverProvider, positionEncoding, referencesProvider, renameProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
75
84
  - **ruby**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, diagnosticProvider, documentHighlightProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, experimental, foldingRangeProvider, hoverProvider, inlayHintProvider, positionEncoding, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeHierarchyProvider, workspaceSymbolProvider
76
85
  - **rust**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, declarationProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, positionEncoding, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
77
86
  - **svelte**: callHierarchyProvider, codeActionProvider, codeLensProvider, colorProvider, completionProvider, definitionProvider, diagnosticProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, linkedEditingRangeProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspaceSymbolProvider
78
87
  - **terraform**: codeActionProvider, codeLensProvider, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentLinkProvider, documentSymbolProvider, executeCommandProvider, experimental, hoverProvider, referencesProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
88
+ - **tinymist**: codeActionProvider, codeLensProvider, colorProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentLinkProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, inlayHintProvider, positionEncoding, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
79
89
  - **toml**: completionProvider, documentFormattingProvider, documentLinkProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, renameProvider, semanticTokensProvider, textDocumentSync, workspace
80
90
  - **typescript**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, linkedEditingRangeProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
81
91
  - **typos**: codeActionProvider, executeCommandProvider, positionEncoding, textDocumentSync, workspace
@@ -91,15 +101,19 @@ surface, including providers pi-lens does not yet consume.
91
101
 
92
102
  - **ast-grep** (1): ast-grep.applyAllFixes
93
103
  - **clojure** (62): add-import-to-namespace, add-missing-import, add-missing-libspec, add-require-suggestion, as-to-refer, backward, backward-barf, backward-select, backward-slurp, change-coll, clean-ns, cond->if-refactor, create-function, create-test, cursor-info, cycle-coll, cycle-keyword-auto-resolve, cycle-privacy, demote-fn, destructure-keys, drag-backward, drag-forward, drag-param-backward, drag-param-forward, expand-let, extract-function, extract-to-def, forward, forward-barf, forward-select, forward-slurp, get-in-all, get-in-less, get-in-more, get-in-none, if->cond-refactor, inline-function, inline-symbol, introduce-let, kill-sexp, …
104
+ - **cpp** (3): clangd.applyFix, clangd.applyRename, clangd.applyTweak
94
105
  - **cue** (1): cuelsp.externalvalidate
95
- - **dart** (18): dart.edit.codeAction.apply, dart.edit.sortMembers, dart.edit.organizeImports, dart.edit.fixAll, dart.edit.fixAllInWorkspace.preview, dart.edit.fixAllInWorkspace, dart.edit.sendWorkspaceEdit, refactor.perform, refactor.validate, dart.logAction, dart.refactor.add_constructor_name, dart.refactor_add.import_prefix, dart.refactor.convert_all_formal_parameters_to_named, dart.refactor.convert_selected_formal_parameters_to_named, dart.refactor.move_selected_formal_parameters_left, dart.refactor.move_top_level_to_file, dart.refactor.remove_constructor_name, dart.refactor.remove_import_prefix
106
+ - **dart** (18): dart.edit.codeAction.apply, dart.edit.fixAll, dart.edit.fixAllInWorkspace, dart.edit.fixAllInWorkspace.preview, dart.edit.organizeImports, dart.edit.sendWorkspaceEdit, dart.edit.sortMembers, dart.logAction, dart.refactor.add_constructor_name, dart.refactor.convert_all_formal_parameters_to_named, dart.refactor.convert_selected_formal_parameters_to_named, dart.refactor.move_selected_formal_parameters_left, dart.refactor.move_top_level_to_file, dart.refactor.remove_constructor_name, dart.refactor.remove_import_prefix, dart.refactor_add.import_prefix, refactor.perform, refactor.validate
96
107
  - **deno** (2): deno.cache, deno.reloadImportRegistries
108
+ - **emmylua** (4): fake.applyEdit, fake.applyEditDeferred, fake.doThing, fake.releaseDeferredApplyEdit
97
109
  - **expert** (2): Reindex, connectionDetails
110
+ - **fish** (22): fish-lsp.checkHealth, fish-lsp.createTheme, fish-lsp.execute, fish-lsp.executeBuffer, fish-lsp.executeLine, fish-lsp.executeRange, fish-lsp.fixAll, fish-lsp.generateEnvVariables, fish-lsp.showEnvVariables, fish-lsp.showInfo, fish-lsp.showReferences, fish-lsp.showStatusDocs, fish-lsp.showWorkspaceMessage, fish-lsp.toggleSingleWorkspaceSupport, fish-lsp.updateWorkspace, quickfix.delete, quickfix.disable, quickfix.fix, quickfix.fixAll, refactor.extract, refactor.rewrite, source.rename
98
111
  - **go** (47): gopls.add_dependency, gopls.add_import, gopls.add_telemetry_counters, gopls.add_test, gopls.apply_fix, gopls.assembly, gopls.change_signature, gopls.check_upgrades, gopls.client_open_url, gopls.diagnose_files, gopls.doc, gopls.edit_go_directive, gopls.extract_to_new_file, gopls.fetch_vulncheck_result, gopls.free_symbols, gopls.gc_details, gopls.generate, gopls.go_get_package, gopls.implement_interface, gopls.list_imports, gopls.list_known_packages, gopls.lsp, gopls.maybe_prompt_for_telemetry, gopls.mem_stats, gopls.modify_tags, gopls.modules, gopls.move_type, gopls.package_symbols, gopls.packages, gopls.regenerate_cgo, gopls.remove_dependency, gopls.reset_go_mod_diagnostics, gopls.run_go_work_command, gopls.run_govulncheck, gopls.run_tests, gopls.scan_imports, gopls.split_package, gopls.start_debugging, gopls.start_profile, gopls.stop_profile, …
99
- - **lua** (6): lua.removeSpace, lua.solve, lua.jsonToLua, lua.setConfig, lua.getConfig, lua.autoRequire
100
- - **opengrep** (2): semgrep/ignore, semgrep/autofix
112
+ - **lua** (6): lua.autoRequire, lua.getConfig, lua.jsonToLua, lua.removeSpace, lua.setConfig, lua.solve
113
+ - **opengrep** (2): semgrep/autofix, semgrep/ignore
101
114
  - **terraform** (7): terraform-ls.module.callers, terraform-ls.module.calls, terraform-ls.module.providers, terraform-ls.module.terraform, terraform-ls.rootmodules, terraform-ls.terraform.init, terraform-ls.terraform.validate
102
- - **typescript** (8): _typescript.applyRefactoring, _typescript.configurePlugin, _typescript.organizeImports, _typescript.applyRenameFile, _typescript.goToSourceDefinition, _typescript.applyCodeActionCommand, _typescript.applyFixAllCodeAction, typescript.tsserverRequest
115
+ - **tinymist** (29): tinymist.doClearCache, tinymist.doGetTemplateEntry, tinymist.doInitTemplate, tinymist.doKillPreview, tinymist.doStartBrowsingPreview, tinymist.doStartPreview, tinymist.exportAnsiHighlight, tinymist.exportAst, tinymist.exportBundle, tinymist.exportHtml, tinymist.exportMarkdown, tinymist.exportPdf, tinymist.exportPng, tinymist.exportQuery, tinymist.exportSvg, tinymist.exportTeX, tinymist.exportText, tinymist.focusMain, tinymist.getDocumentMetrics, tinymist.getDocumentTrace, tinymist.getResources, tinymist.getServerInfo, tinymist.getWorkspaceLabels, tinymist.interactCodeContext, tinymist.pinMain, tinymist.scrollPreview, tinymist.startDefaultPreview, tinymist.startServerProfiling, tinymist.stopServerProfiling
116
+ - **typescript** (8): _typescript.applyCodeActionCommand, _typescript.applyFixAllCodeAction, _typescript.applyRefactoring, _typescript.applyRenameFile, _typescript.configurePlugin, _typescript.goToSourceDefinition, _typescript.organizeImports, typescript.tsserverRequest
103
117
  - **typos** (1): ignore-in-project
104
118
  - **yaml** (1): jumpToSchema
105
119
 
@@ -108,11 +122,7 @@ surface, including providers pi-lens does not yet consume.
108
122
  Toolchain/binary not installed here, so capabilities weren't captured
109
123
  (many are the toolchain-gated family tracked in #241):
110
124
 
111
- - @prisma/language-server
112
- - PowerShell Editor Services (pwsh Start-EditorServices.ps1 -Stdio)
113
- - clangd
114
125
  - cmake-language-server
115
- - fish-lsp
116
126
  - haskell-language-server
117
127
  - jdtls
118
128
  - jdtls + lombok javaagent
@@ -29,7 +29,8 @@ contract.
29
29
  CI-scoped switches and for the handful of tuning knobs that have no config key.
30
30
  2. **CLI flags** (`--no-lsp`, `--immediate-format`, …) — per-session, passed on
31
31
  the pi command line.
32
- 3. **Config JSON** — a per-user global file (`~/.pi-lens/config.json`) and an
32
+ 3. **Config JSON** — a per-user global file selected by the
33
+ [global-location table](configuration.md#global-config-location) and an
33
34
  optional per-project file (`.pi-lens.json` at the repo root).
34
35
 
35
36
  Every runtime toggle is settable **both** from the CLI and from `config.json`;
@@ -108,6 +109,9 @@ tool. The loader `pi_lens_activate_tools` and MCP lifecycle tools
108
109
  required by their host protocols and cannot be disabled. Unknown or
109
110
  non-disableable names emit `PILENS_CFG_0009`.
110
111
 
112
+ When a lower-precedence supported global config file is shadowed by the
113
+ winning file, pi-lens records the notice once with `PILENS_CFG_0010`.
114
+
111
115
  Valid names for `tools.<name>.enabled` include `ast_grep_search`,
112
116
  `ast_grep_replace`, `ast_grep_outline`, `lsp_navigation`,
113
117
  `lens_diagnostics`, `lens_diagnostic_mark`, `symbol_search`,
@@ -149,9 +153,10 @@ field docs.
149
153
 
150
154
  ## Global vs project config
151
155
 
152
- ### Global — `~/.pi-lens/config.json`
156
+ ### Global — winning location
153
157
 
154
- User-level. Applies to **every** project. Honors **all** flag keys from the
158
+ User-level. The file is selected by the [global-location table](configuration.md#global-config-location)
159
+ and applies to **every** project. It honors **all** flag keys from the
155
160
  table above plus the non-flag global knobs (`ignore`, `widget.visible`,
156
161
  `dispatch.runnerTimeoutFloorMs`, `format.mode`,
157
162
  `actionableWarnings.autoFix.maxFixes`). On Windows the path is
@@ -238,6 +243,10 @@ manager, or CI config. The handful you are most likely to reach for:
238
243
  review graph) out of the workspace.
239
244
  - `PI_LENS_HOME` — relocate the machine-global root (logs, tool binaries, install
240
245
  caches, instance registry).
246
+ - `PI_LENS_CONFIG_PATH` — point the global config file at an explicit path.
247
+ - `PI_CODING_AGENT_DIR` — when pi sets it, `$PI_CODING_AGENT_DIR/extensions/
248
+ pi-lens.json` is read when it exists and the default global config file does
249
+ not; pi-lens does not write the file.
241
250
  - `PI_LENS_MAX_PROJECT_FILES` — base project-size scale knob (default `2000`).
242
251
  - `PI_LENS_STARTUP_MODE` — force the startup path: `full`, `minimal`, or `quick`.
243
252
 
@@ -17,7 +17,7 @@ every run.
17
17
 
18
18
  | # | Contract | Depended on by | Third-party file (as of the versions below) | Verified against |
19
19
  |---|----------|-----------------|-------------------------------------------------|-------------------|
20
- | 1 | `PI_SUBAGENT_CHILD` is set to the literal string `"1"` on every process that hosts a child session. | `clients/subagent-mode.ts` (`isSubagentSession()`, `getSubagentIdentity()`) | `pi-subagents@0.34.0` — co-located in `src/runs/shared/pi-args.ts` (`SUBAGENT_CHILD_ENV` const + the `env[SUBAGENT_CHILD_ENV] = "1"` assignment); as of `pi-subagents@0.66.0` the const moved to `src/runs/shared/child-runtime-config.ts` and the assignment to `src/runs/background/subagent-runner.ts` (#2581) — `compat-contract-locator.mjs`'s `locateContractSources` tries both layouts and concatenates whichever resolves. | `checkNicobailonChildEnv` |
20
+ | 1 | `PI_SUBAGENT_CHILD` is set to the literal string `"1"` on every process that hosts a child session. | `clients/subagent-mode.ts` (`isSubagentSession()`, `getSubagentIdentity()`) | `pi-subagents@0.34.0` — co-located in `src/runs/shared/pi-args.ts` (`SUBAGENT_CHILD_ENV` const + the `env[SUBAGENT_CHILD_ENV] = "1"` assignment); as of `pi-subagents@0.66.0` the const moved to `src/runs/shared/child-runtime-config.ts` and the assignment to `src/runs/background/subagent-runner.ts` (#2581); as of `0.70.0`, the published files are `src/runs/shared/child-runtime-config.js` and `src/runs/background/subagent-runner.js` — `compat-contract-locator.mjs`'s `locateContractSources` tries all layouts and concatenates whichever resolves. | `checkNicobailonChildEnv` |
21
21
  | 1b | avtc-pi-subagent sets `PI_SUBAGENT_CHILD_AGENT` + `PI_SUBAGENT_PARENT_PID` (never `PI_SUBAGENT_CHILD`) on the per-spawn subagent env; `isSubagentSession()` treats the PAIR (both non-empty) as an additional subagent signal (#507). | `clients/subagent-mode.ts` (`isSubagentSession()`, `getSubagentIdentity()`) | `avtc-pi-subagent@1.0.3` — `src/process-runner.ts` (`subagentEnv.PI_SUBAGENT_CHILD_AGENT = agent.name` + `subagentEnv.PI_SUBAGENT_PARENT_PID = String(process.pid)`) | `checkAvtcChildEnv` |
22
22
  | 2a | The pi SDK's extension loader keeps a **process-global** cache (`extensionCache = new Map()`). This is what makes an in-process `bindExtensions()` reuse pi-lens's own module-scope singletons instead of a fresh isolated instance. | `clients/session-lifecycle.ts` (the whole premise of the concurrent-session guard) | `@earendil-works/pi-coding-agent@0.80.6` — `dist/core/extensions/loader.js` | `checkSdkExtensionCache` |
23
23
  | 2b | `AgentSession.bindExtensions()` **unconditionally** emits a `session_start`-typed event (`this._extensionRunner.emit(this._sessionStartEvent)`). | Same as 2a — this is why an in-process subagent bind re-triggers pi-lens's `session_start` handler at all. | `@earendil-works/pi-coding-agent@0.80.6` — `dist/core/agent-session.js` (`bindExtensions()`, ~line 1717) | `checkSdkBindExtensionsEmitsSessionStart` |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lens",
3
- "version": "4.2.1",
3
+ "version": "4.3.0",
4
4
  "type": "module",
5
5
  "description": "Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo",
6
6
  "repository": {
@@ -20,9 +20,10 @@
20
20
  "prepare": "npm run build:dist && node scripts/download-grammars.js --core --dest grammars && node scripts/setup-git-hooks.mjs && node scripts/warm-loader-cache.mjs",
21
21
  "prepack": "node scripts/strip-dev-deps-for-pack.mjs --strip",
22
22
  "postpack": "node scripts/strip-dev-deps-for-pack.mjs --restore",
23
- "lint": "tsc --project tsconfig.json && npm run lint:js",
23
+ "lint": "tsc --project tsconfig.json && npm run lint:js && npm run lint:js:tests",
24
24
  "lint:js": "oxlint --deny-warnings --import-plugin --promise-plugin -D block-scoped-var -D import/default -D import/namespace -D import/no-absolute-path -D import/no-empty-named-blocks -D import/no-named-as-default -D import/no-self-import -D no-extend-native -D no-extra-bind -D no-implied-eval -D no-new -D no-unexpected-multiline -D no-useless-constructor -D oxc/approx-constant -D oxc/misrefactored-assign-op -D oxc/no-accumulating-spread -D oxc/no-async-endpoint-handlers -D oxc/no-this-in-exported-function -D promise/no-callback-in-promise -D promise/no-multiple-resolved -D promise/no-new-statics -D promise/valid-params -D typescript/no-confusing-non-null-assertion -D typescript/no-extraneous-class -D typescript/no-unnecessary-type-constraint -D typescript/no-unsafe-enum-comparison -D unicorn/no-accessor-recursion -D unicorn/no-array-fill-with-reference-type -D unicorn/no-confusing-array-with -D unicorn/no-instanceof-builtins -D unicorn/prefer-array-flat-map -D unicorn/require-module-specifiers --ignore-pattern \"tests/**/*.ts\" --ignore-pattern \"tests/**/*.tsx\" --ignore-pattern \"**/*.d.mts\" --ignore-pattern \"tests/fixtures/autofix-smoke/**\" --ignore-pattern \"tests/fixtures/format-smoke/**\" --ignore-pattern \"tests/fixtures/tool-smoke/**\" --ignore-pattern \"tests/fixtures/call-graph/javascript/**\" --ignore-pattern \"tests/fixtures/function-facts/javascript-parameter.js\" .",
25
- "lint:js:advisory": "node scripts/lint-js-advisory.mjs --deny-warnings --format default -D correctness -D suspicious -D perf --import-plugin --promise-plugin --type-aware -A no-underscore-dangle -A no-await-in-loop -A unicorn/no-array-sort -A unicorn/consistent-function-scoping -A promise/no-promise-in-callback -A no-useless-call -A import/no-unassigned-import -A no-unmodified-loop-condition --ignore-pattern \"**/*.d.mts\" --ignore-pattern \"tests/fixtures/autofix-smoke/**\" --ignore-pattern \"tests/fixtures/format-smoke/**\" --ignore-pattern \"tests/fixtures/tool-smoke/**\" --ignore-pattern \"tests/fixtures/call-graph/javascript/**\" --ignore-pattern \"tests/fixtures/function-facts/javascript-parameter.js\" .",
25
+ "lint:js:advisory": "node scripts/lint-js-advisory.mjs --deny-warnings --format unix -D correctness -D suspicious -D perf --import-plugin --promise-plugin --type-aware -A no-underscore-dangle -A no-await-in-loop -A unicorn/no-array-sort -A unicorn/consistent-function-scoping -A promise/no-promise-in-callback -A no-useless-call -A import/no-unassigned-import -A no-unmodified-loop-condition --ignore-pattern \"**/*.d.mts\" --ignore-pattern \"tests/fixtures/autofix-smoke/**\" --ignore-pattern \"tests/fixtures/format-smoke/**\" --ignore-pattern \"tests/fixtures/tool-smoke/**\" --ignore-pattern \"tests/fixtures/call-graph/javascript/**\" --ignore-pattern \"tests/fixtures/function-facts/javascript-parameter.js\" .",
26
+ "lint:js:tests": "node scripts/lint-js-advisory.mjs --deny-warnings --format unix --type-aware -A correctness -A suspicious -A perf --ignore-pattern \"tests/fixtures/**\" tests",
26
27
  "depcruise:check": "depcruise --validate --config .dependency-cruiser.cjs --ignore-known .dependency-cruiser-known-violations.json --output-type err index.ts \"clients/**/*.ts\"",
27
28
  "fmt": "oxfmt",
28
29
  "fmt:check": "oxfmt --check",
@@ -103,6 +104,7 @@
103
104
  "scripts/install-selftest.mjs",
104
105
  "scripts/lib/host-provided-deps.mjs",
105
106
  "scripts/lib/skills-predicate.mjs",
107
+ "scripts/lib/web-tree-sitter-dir.mjs",
106
108
  "scripts/lib/warm-loader-cache.mjs",
107
109
  "scripts/warm-loader-cache.mjs",
108
110
  "scripts/rpc-load-check.mjs",
@@ -4,9 +4,22 @@ valid:
4
4
  - 'assert x == 1'
5
5
  - 'assert x, "message"'
6
6
  - 'assert (x == 1), "message"' # explicit grouping, not a tuple
7
+ - 'assert actual == (1, 2)'
8
+ - 'assert (actual == (1, 2))'
9
+ - 'assert (f((1, 2)))'
10
+ - 'assert (left, right) == expected'
11
+ - 'assert value in {(1, 2), (3, 4)}'
12
+ - 'assert {item for item in values if item != (1, 2)}'
13
+ - 'assert all(item in {(1, 2)} for item in values)'
14
+ - 'assert True, ("tuple", "message")'
15
+ - 'assert actual == (1, 2), ("tuple", "message")'
7
16
  invalid:
17
+ - 'assert ()'
8
18
  - 'assert (1, 2)'
9
19
  - 'assert (x, y)'
20
+ - 'assert ((x, y))'
21
+ - 'assert (((x, y)))'
22
+ - 'assert (x, y), ("tuple", "message")'
10
23
  - 'assert (1, 2, 3), "message"'
11
24
  - |
12
25
  def f():