@herbertgao/pi-extensions 2026.9.0 → 2026.9.1

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 (293) 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/@pi-plugins/fast-mode/README.md +5 -3
  11. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  12. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
  13. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  14. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  15. package/node_modules/pi-lens/CHANGELOG.md +988 -0
  16. package/node_modules/pi-lens/README.md +3 -0
  17. package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
  18. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
  19. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -2
  20. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
  21. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
  22. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
  23. package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
  24. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -2
  25. package/node_modules/pi-lens/dist/clients/bash-file-access.js +1 -3
  26. package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
  27. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -0
  28. package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
  29. package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
  30. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -4
  31. package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
  32. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +2 -2
  33. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
  34. package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
  35. package/node_modules/pi-lens/dist/clients/cache-observability.js +44 -18
  36. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
  37. package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -2
  38. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
  39. package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
  40. package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
  41. package/node_modules/pi-lens/dist/clients/config-core/index.js +47 -0
  42. package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
  43. package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
  44. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
  45. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +171 -0
  46. package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
  47. package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
  48. package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
  49. package/node_modules/pi-lens/dist/clients/config-core/schema.js +167 -0
  50. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
  51. package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
  52. package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
  53. package/node_modules/pi-lens/dist/clients/config-schema.js +197 -0
  54. package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
  55. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
  56. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -2
  57. package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
  58. package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
  59. package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
  60. package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
  61. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
  62. package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
  63. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
  64. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +14 -4
  65. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -18
  66. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
  67. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -7
  68. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
  69. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +380 -26
  70. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
  71. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -1
  72. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
  73. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
  74. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
  75. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
  76. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
  77. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
  78. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
  79. package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
  80. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
  81. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
  82. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
  83. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
  84. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
  85. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
  86. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -1
  87. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +13 -18
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -1
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -1
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -1
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -4
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -1
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
  121. package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -3
  122. package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
  123. package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
  124. package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
  125. package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
  126. package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
  127. package/node_modules/pi-lens/dist/clients/file-time.js +6 -1
  128. package/node_modules/pi-lens/dist/clients/file-utils.js +112 -9
  129. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
  130. package/node_modules/pi-lens/dist/clients/format-service.js +6 -1
  131. package/node_modules/pi-lens/dist/clients/formatters.js +276 -102
  132. package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
  133. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +114 -19
  134. package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
  135. package/node_modules/pi-lens/dist/clients/git-guard.js +1 -1
  136. package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
  137. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
  138. package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
  139. package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
  140. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
  141. package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
  142. package/node_modules/pi-lens/dist/clients/installer/index.js +71 -52
  143. package/node_modules/pi-lens/dist/clients/instance-reaper.js +104 -230
  144. package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
  145. package/node_modules/pi-lens/dist/clients/language-registry.js +595 -0
  146. package/node_modules/pi-lens/dist/clients/latency-logger.js +160 -2
  147. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +13 -0
  148. package/node_modules/pi-lens/dist/clients/lens-config.js +141 -30
  149. package/node_modules/pi-lens/dist/clients/lens-engine.js +30 -37
  150. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +59 -6
  151. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -2
  152. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
  153. package/node_modules/pi-lens/dist/clients/lsp/client.js +168 -30
  154. package/node_modules/pi-lens/dist/clients/lsp/config.js +483 -158
  155. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
  156. package/node_modules/pi-lens/dist/clients/lsp/edits.js +15 -2
  157. package/node_modules/pi-lens/dist/clients/lsp/index.js +676 -71
  158. package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -169
  159. package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
  160. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -16
  161. package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
  162. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
  163. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
  164. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +9 -2
  165. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
  166. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
  167. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
  168. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
  169. package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
  170. package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
  171. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +2 -4
  172. package/node_modules/pi-lens/dist/clients/module-report.js +20 -45
  173. package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
  174. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
  175. package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
  176. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -20
  177. package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
  178. package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
  179. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +68 -22
  180. package/node_modules/pi-lens/dist/clients/opengrep-config.js +4 -0
  181. package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
  182. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
  183. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
  184. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
  185. package/node_modules/pi-lens/dist/clients/path-utils.js +428 -13
  186. package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
  187. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
  188. package/node_modules/pi-lens/dist/clients/pipeline.js +77 -16
  189. package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
  190. package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
  191. package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
  192. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
  193. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +27 -3
  194. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
  195. package/node_modules/pi-lens/dist/clients/project-lens-config.js +393 -122
  196. package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
  197. package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
  198. package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
  199. package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
  200. package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
  201. package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
  202. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +15 -4
  203. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
  204. package/node_modules/pi-lens/dist/clients/read-guard.js +21 -0
  205. package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
  206. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +152 -109
  207. package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
  208. package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
  209. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
  210. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
  211. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +18 -2
  212. package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
  213. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
  214. package/node_modules/pi-lens/dist/clients/runtime-session.js +139 -22
  215. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +168 -35
  216. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
  217. package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
  218. package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
  219. package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
  220. package/node_modules/pi-lens/dist/clients/sanitize.js +7 -1
  221. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
  222. package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
  223. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
  224. package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
  225. package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
  226. package/node_modules/pi-lens/dist/clients/sgconfig.js +6 -1
  227. package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
  228. package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
  229. package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
  230. package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
  231. package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
  232. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +239 -0
  233. package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
  234. package/node_modules/pi-lens/dist/clients/tool-policy.js +91 -21
  235. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +86 -48
  237. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  238. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
  239. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
  240. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
  241. package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
  242. package/node_modules/pi-lens/dist/clients/user-notify.js +6 -2
  243. package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
  244. package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -2
  245. package/node_modules/pi-lens/dist/clients/word-index-store.js +20 -5
  246. package/node_modules/pi-lens/dist/clients/word-index.js +243 -31
  247. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
  248. package/node_modules/pi-lens/dist/clients/zizmor-config.js +3 -0
  249. package/node_modules/pi-lens/dist/index.js +64335 -54300
  250. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
  251. package/node_modules/pi-lens/dist/mcp/server.js +127 -5
  252. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
  253. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
  254. package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
  255. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +95 -24
  256. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +67 -80
  257. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
  258. package/node_modules/pi-lens/dist/tools/shared.js +0 -1
  259. package/node_modules/pi-lens/docs/agent-guide.md +64 -1
  260. package/node_modules/pi-lens/docs/configuration.md +222 -0
  261. package/node_modules/pi-lens/docs/dependencies.md +3 -3
  262. package/node_modules/pi-lens/docs/features.md +44 -5
  263. package/node_modules/pi-lens/docs/language-coverage.md +2 -2
  264. package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
  265. package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
  266. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +27 -0
  267. package/node_modules/pi-lens/docs/pi-lens-subagent.md +38 -0
  268. package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
  269. package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
  270. package/node_modules/pi-lens/docs/release-qa-baseline.md +182 -0
  271. package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
  272. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
  273. package/node_modules/pi-lens/package.json +15 -23
  274. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
  275. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
  276. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
  277. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
  278. package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
  279. package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
  280. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
  281. package/node_modules/pi-web-access/CHANGELOG.md +28 -0
  282. package/node_modules/pi-web-access/README.md +62 -15
  283. package/node_modules/pi-web-access/curator-page.ts +3 -1
  284. package/node_modules/pi-web-access/curator-server.ts +5 -1
  285. package/node_modules/pi-web-access/gemini-search.ts +8 -4
  286. package/node_modules/pi-web-access/github-extract.ts +242 -1
  287. package/node_modules/pi-web-access/index.ts +118 -64
  288. package/node_modules/pi-web-access/mistral-search.ts +281 -0
  289. package/node_modules/pi-web-access/package.json +2 -2
  290. package/node_modules/pi-web-access/perplexity.ts +14 -1
  291. package/node_modules/pi-web-access/utils.ts +23 -6
  292. package/node_modules/pi-web-access/xai-search.ts +96 -33
  293. package/package.json +5 -5
@@ -17,15 +17,16 @@ import { logExtension } from "../extension-log.js";
17
17
  import * as fs from "node:fs";
18
18
  import * as path from "node:path";
19
19
  import { recordRunner } from "../widget-state.js";
20
- import { incrementDegradationCount } from "../degradation-ledger.js";
20
+ import { incrementDegradationCount, recordDegradationOnce, } from "../degradation-ledger.js";
21
21
  import { detectFileKind } from "../file-kinds.js";
22
22
  import { detectFileRole } from "../file-role.js";
23
+ import { classifyGeneratedOrArtifactDetailed, } from "../generated-artifacts.js";
23
24
  import { isTestFile } from "../file-utils.js";
24
25
  import { getPrimaryDispatchGroup } from "../language-policy.js";
25
26
  import { resolveLanguageRootForFile } from "../language-profile.js";
26
27
  import { logLatency, phaseFinished, phaseStarted } from "../latency-logger.js";
27
28
  import { isSpawnableCommand } from "../installer/index.js";
28
- import { normalizeEphemeralMapKey, normalizeMapKey } from "../path-utils.js";
29
+ import { isAbsoluteFilePath, normalizeEphemeralMapKey, normalizeMapKey, } from "../path-utils.js";
29
30
  import { loadPiLensProjectConfig } from "../project-lens-config.js";
30
31
  import { RUNTIME_CONFIG, getRunnerTimeoutFloorMs } from "../runtime-config.js";
31
32
  import { safeSpawnAsync } from "../safe-spawn.js";
@@ -61,7 +62,7 @@ export class RunnerRegistry {
61
62
  for (const runner of this.runners.values()) {
62
63
  if (isTest && runner.skipTestFiles)
63
64
  continue;
64
- if (runner.appliesTo.includes(kind) || runner.appliesTo.length === 0) {
65
+ if (runnerAppliesToKind(runner, kind)) {
65
66
  matching.push(runner);
66
67
  }
67
68
  }
@@ -74,6 +75,10 @@ export class RunnerRegistry {
74
75
  this.runners.clear();
75
76
  }
76
77
  }
78
+ function runnerAppliesToKind(runner, kind) {
79
+ return (runner.appliesTo.length === 0 ||
80
+ (kind !== undefined && runner.appliesTo.includes(kind)));
81
+ }
77
82
  // --- Tool Availability Cache ---
78
83
  /**
79
84
  * Normalize a command name to a FactStore session key.
@@ -245,7 +250,19 @@ telemetryModel, telemetryProvider) {
245
250
  const normalizedCwd = normalizeMapKey(resolveLanguageRootForFile(absoluteFilePath, cwd));
246
251
  const normalizedFilePath = normalizeMapKey(absoluteFilePath);
247
252
  const kind = detectFileKind(normalizedFilePath);
248
- const fileRole = detectFileRole(normalizedFilePath, readFilePrefix(normalizedFilePath));
253
+ const contentPrefix = readFilePrefix(normalizedFilePath);
254
+ const fileRole = detectFileRole(normalizedFilePath, contentPrefix);
255
+ // Captured once here so the generated short-circuit below can emit a
256
+ // `dispatch_skipped_generated` record carrying the deciding evidence tier
257
+ // and the measured line-shape statistic — without re-reading the file
258
+ // (refs #2346). The content passed is the same 4096-byte prefix already
259
+ // read for role detection, so this classification costs no extra I/O.
260
+ const generatedDetail = fileRole === "generated"
261
+ ? classifyGeneratedOrArtifactDetailed(normalizedFilePath, {
262
+ content: contentPrefix,
263
+ includeDeclarations: false,
264
+ })
265
+ : undefined;
249
266
  const projectConfig = loadPiLensProjectConfig(normalizedCwd);
250
267
  return {
251
268
  filePath: normalizedFilePath,
@@ -253,6 +270,8 @@ telemetryModel, telemetryProvider) {
253
270
  cwd: normalizedCwd,
254
271
  kind,
255
272
  fileRole,
273
+ generatedEvidence: generatedDetail?.evidence,
274
+ generatedLineShapeMean: generatedDetail?.lineShapeMean,
256
275
  pi,
257
276
  autofix: false,
258
277
  deltaMode: !pi.getFlag("no-delta"),
@@ -462,7 +481,9 @@ function buildCoverageNotice(ctx, runnerLatencies) {
462
481
  const primaryHasCoverage = relevant.some((r) => r.status === "succeeded" || r.status === "failed");
463
482
  if (primaryHasCoverage)
464
483
  return undefined;
465
- const allPrimarySkipped = relevant.every((r) => r.status === "skipped" || r.status === "when_skipped");
484
+ const allPrimarySkipped = relevant.every((r) => r.status === "skipped" ||
485
+ r.status === "when_skipped" ||
486
+ r.status === "test_file_skipped");
466
487
  if (!allPrimarySkipped)
467
488
  return undefined;
468
489
  const plan = getToolPlan(ctx.kind);
@@ -499,6 +520,11 @@ function buildCoverageNotice(ctx, runnerLatencies) {
499
520
  }
500
521
  const latencyReports = [];
501
522
  const coverageNoticeSeen = new Set();
523
+ // One `dispatch_skipped_generated` phase record per file per process (refs
524
+ // #2346): a generated file dispatched repeatedly must not spam latency.log,
525
+ // so only the first skip of each file emits the row; the degradation ledger
526
+ // below still tallies every repetition with a bounded per-subject count.
527
+ const generatedSkipRecorded = new Set();
502
528
  export function getLatencyReports() {
503
529
  return [...latencyReports];
504
530
  }
@@ -507,6 +533,7 @@ export function clearLatencyReports() {
507
533
  }
508
534
  export function clearCoverageNoticeState() {
509
535
  coverageNoticeSeen.clear();
536
+ generatedSkipRecorded.clear();
510
537
  }
511
538
  export function formatLatencyReport(report) {
512
539
  const lines = [];
@@ -588,6 +615,59 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
588
615
  });
589
616
  continue;
590
617
  }
618
+ // Same skipTestFiles gate RunnerRegistry.getForKind applies for the
619
+ // per-edit path (#2337): the plan/group path resolves runners by id via
620
+ // registry.get() instead, which bypasses getForKind entirely, so a
621
+ // runner declaring skipTestFiles never had it enforced here.
622
+ if (runner.skipTestFiles && isTestFile(ctx.filePath)) {
623
+ latencies.push({
624
+ runnerId,
625
+ startTime: runnerStart,
626
+ endTime: Date.now(),
627
+ durationMs: Date.now() - runnerStart,
628
+ status: "test_file_skipped",
629
+ diagnosticCount: 0,
630
+ semantic: "none",
631
+ });
632
+ logLatency({
633
+ type: "runner",
634
+ filePath: ctx.filePath,
635
+ runnerId,
636
+ durationMs: 0,
637
+ status: "test_file_skipped",
638
+ diagnosticCount: 0,
639
+ semantic: "none",
640
+ });
641
+ continue;
642
+ }
643
+ // Keep explicit groups aligned with RunnerRegistry.getForKind(): an empty
644
+ // appliesTo list means every kind, while a populated list must contain the
645
+ // current kind. A filtered runner remains visible as skipped telemetry so
646
+ // language mismatches cannot be mistaken for runner failures.
647
+ const appliesToCurrentKind = runnerAppliesToKind(runner, ctx.kind);
648
+ if (!appliesToCurrentKind) {
649
+ const runnerEnd = Date.now();
650
+ latencies.push({
651
+ runnerId,
652
+ startTime: runnerStart,
653
+ endTime: runnerEnd,
654
+ durationMs: 0,
655
+ status: "skipped",
656
+ diagnosticCount: 0,
657
+ semantic: "unknown",
658
+ });
659
+ logLatency({
660
+ type: "runner",
661
+ filePath: ctx.filePath,
662
+ runnerId,
663
+ durationMs: 0,
664
+ status: "skipped",
665
+ diagnosticCount: 0,
666
+ semantic: "unknown",
667
+ metadata: { reason: "applies_to", kind: ctx.kind },
668
+ });
669
+ continue;
670
+ }
591
671
  // Check preconditions
592
672
  let shouldRun = true;
593
673
  if (runner.when) {
@@ -802,6 +882,31 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
802
882
  export async function dispatchForFile(ctx, groups, registry, onRunnerResult) {
803
883
  const _overallStart = Date.now();
804
884
  if (ctx.fileRole === "generated") {
885
+ // The generated short-circuit (refs #2346): never ran before this fix
886
+ // for name-less machine-emitted files (a scraped/minified page has no
887
+ // `.min.js` pattern to catch it), so the classification now also has a
888
+ // content-shape tier. The skip is observable — one `dispatch_skipped_generated`
889
+ // phase record per file per process carrying the deciding evidence tier
890
+ // and the measured line-shape statistic. Deliberately NOT a degradation
891
+ // ledger entry: skipping a generated file is healthy behavior working
892
+ // as designed, and the ledger's bounded kind slots are reserved for
893
+ // genuine degradations (#2348 review F3 — the ledger precedent at the
894
+ // collect-later tier flip below records an actual capability loss).
895
+ const evidence = ctx.generatedEvidence;
896
+ const lineShapeMean = ctx.generatedLineShapeMean;
897
+ if (!generatedSkipRecorded.has(ctx.filePath)) {
898
+ generatedSkipRecorded.add(ctx.filePath);
899
+ logLatency({
900
+ type: "phase",
901
+ filePath: ctx.filePath,
902
+ phase: "dispatch_skipped_generated",
903
+ durationMs: 0,
904
+ metadata: {
905
+ evidence: evidence ?? "unknown",
906
+ ...(lineShapeMean !== undefined && { lineShapeMean }),
907
+ },
908
+ });
909
+ }
805
910
  return {
806
911
  diagnostics: [],
807
912
  blockers: [],
@@ -836,17 +941,46 @@ export async function dispatchForFile(ctx, groups, registry, onRunnerResult) {
836
941
  // group order so output is deterministic.
837
942
  const groupResults = await Promise.all(groups.map((group) => runGroup(ctx, group, registry, onRunnerResult)));
838
943
  // Count baseline warnings before filtering (for delta count display)
839
- const relativeKey = path.relative(ctx.cwd, ctx.filePath).replace(/\\/g, "/");
944
+ //
945
+ // #2489: `ctx.filePath` is `createDispatchContext`'s `normalizedFilePath`
946
+ // (`resolveRunnerPath` -> `path.resolve` -> `normalizeMapKey`), which is
947
+ // ALWAYS absolute — the #2016 invariant this seam already relies on. A
948
+ // prior relative-path fallback key (`session.baseline.<path relative to
949
+ // ctx.cwd>`) existed here for self-consistency across the abs/rel read
950
+ // and write, but on `ctx.facts` singletons that outlive one project root
951
+ // (`dispatch/integration.ts`'s module-scope `sessionFacts`, reached by
952
+ // the warm `pilens_analyze` MCP route across any number of cwds) two
953
+ // different projects dispatching files that share a relative path (e.g.
954
+ // both have `src/index.ts`) collided on that fallback key, so project
955
+ // B's first-ever delta baseline read could silently return project A's
956
+ // stored diagnostics. Since the absolute key can never collide across
957
+ // projects (an absolute path is unique on the filesystem) and both
958
+ // writes always land together, the relative fallback is both unneeded
959
+ // and the sole source of the collision — removed rather than cwd-scoped
960
+ // (`cwd` is not a stable identity across this seam's callers, #2494).
961
+ //
962
+ // #2489 round 2: the #2016 invariant above is enforced by
963
+ // `createDispatchContext`, the sole real constructor, but nothing enforced
964
+ // it AT THIS SEAM — a hand-built `DispatchContext` (test scaffolding, a
965
+ // future caller) carrying a relative `filePath` would silently key the
966
+ // baseline under a value the constructor could never produce, and every
967
+ // subsequent same-session dispatch of the real (absolute-keyed) file would
968
+ // read back `undefined`, never the collision itself. Mirrors the sibling
969
+ // guard `recordEntitySnapshotDiff` already enforces for the entity-snapshot
970
+ // seam (`clients/review-graph/service.ts`, #2477): reject visibly and skip
971
+ // the baseline read/write for this dispatch rather than compute one under
972
+ // an unreachable key.
973
+ const baselinePathSafe = isAbsoluteFilePath(ctx.filePath);
974
+ if (ctx.deltaMode && !baselinePathSafe) {
975
+ recordDegradationOnce({
976
+ kind: "dispatch-non-absolute-baseline-path",
977
+ subject: ctx.filePath,
978
+ reason: "dispatchForFile requires an absolute ctx.filePath to key the delta baseline (refs #2489)",
979
+ });
980
+ }
840
981
  const baselineAbsKey = `session.baseline.${ctx.filePath}`;
841
- // #2016: `relativeKey` is relative to `ctx.cwd`. `normalizeMapKey` resolved
842
- // it against the process cwd instead, so on Windows this "relative" key
843
- // became an absolute path anchored on the wrong root while POSIX left it
844
- // relative. Both the read here and the write below use this const, so the
845
- // key stays self-consistent within a session.
846
- const baselineRelKey = `session.baseline.${normalizeEphemeralMapKey(relativeKey)}`;
847
- const previousBaseline = ctx.deltaMode
848
- ? (ctx.facts.getSessionFact(baselineAbsKey) ??
849
- ctx.facts.getSessionFact(baselineRelKey))
982
+ const previousBaseline = ctx.deltaMode && baselinePathSafe
983
+ ? ctx.facts.getBoundedSessionFact(baselineAbsKey)
850
984
  : undefined;
851
985
  const baselineWarnings = previousBaseline?.filter((d) => d.semantic === "warning" || d.semantic === "none");
852
986
  const baselineWarningCount = baselineWarnings?.length ?? 0;
@@ -913,9 +1047,12 @@ export async function dispatchForFile(ctx, groups, registry, onRunnerResult) {
913
1047
  resolvedCount = filtered.fixed.length;
914
1048
  }
915
1049
  // Persist full current snapshot for next run (not delta-filtered subset).
916
- if (ctx.deltaMode) {
917
- ctx.facts.setSessionFact(baselineAbsKey, [...dedupedDiagnostics]);
918
- ctx.facts.setSessionFact(baselineRelKey, [...dedupedDiagnostics]);
1050
+ // Gated on `baselinePathSafe` too: a non-absolute `ctx.filePath` already
1051
+ // skipped the read above (the degradation record fired there), and writing
1052
+ // under that same unreachable key here would just seed a baseline no real
1053
+ // reader (always absolute) could ever read back.
1054
+ if (ctx.deltaMode && baselinePathSafe) {
1055
+ ctx.facts.setBoundedSessionFact(baselineAbsKey, [...dedupedDiagnostics]);
919
1056
  }
920
1057
  // Categorize results
921
1058
  const blockers = visibleDiagnostics.filter((d) => d.semantic === "blocking");
@@ -1003,6 +1140,13 @@ export async function dispatchForFile(ctx, groups, registry, onRunnerResult) {
1003
1140
  })),
1004
1141
  totalDiagnostics: visibleDiagnostics.length,
1005
1142
  blockers: blockers.length,
1143
+ // #2489 round 2: distinguishes a delta baseline HIT (a prior snapshot
1144
+ // was read for this file this session) from a MISS (first dispatch, or
1145
+ // the non-absolute-path guard above skipped the read) — `dispatch_start`
1146
+ // (above, `metadata: { groupCount, kind, runners }`) fires before the
1147
+ // baseline read ever runs and cannot carry either value.
1148
+ baselineHit: previousBaseline !== undefined,
1149
+ baselineWarningCount,
1006
1150
  },
1007
1151
  });
1008
1152
  return {
@@ -1,3 +1,4 @@
1
+ import { BoundedLruCache } from "../bounded-cache.js";
1
2
  import { normalizeMapKey } from "../path-utils.js";
2
3
  let capacityEvictionReporter;
3
4
  export function setFactStoreEvictionReporter(reporter) {
@@ -17,11 +18,60 @@ const MAX_FILE_FACT_RECORDS = 1024;
17
18
  // preventing a small number of generated or vendored files from retaining
18
19
  // hundreds of MiB for the process lifetime (#2247).
19
20
  const MAX_FILE_FACT_CONTENT_BYTES = 64 * 1024 * 1024;
21
+ // Pinned records are exempt from capacity eviction. A dispatch reads its
22
+ // file's facts back after the runner groups settle (`file.content` misses read as
23
+ // empty content, not as "re-derive"), and the fire-and-forget blast-radius
24
+ // build runs a whole-project walk against the SAME store meanwhile — plain LRU
25
+ // recency would let that walk evict the file being dispatched. Every other holder
26
+ // re-derives an evicted fact from disk.
27
+ //
28
+ // #2243 item 2: a dispatch pins its file at start (`clearFileFactsFor`) and
29
+ // releases it at completion (`endDispatchFor`, in the dispatch's finally). The
30
+ // pin set therefore tracks dispatches actually IN FLIGHT, not the last N files
31
+ // touched.
32
+ // #2282: `sessionFacts` below is a flat `Map<factId, value>` shared by two
33
+ // unrelated fact shapes — a small FIXED vocabulary (tool availability keyed by
34
+ // command, the singleton "session.reviewGraph") and PER-FILE families that
35
+ // mint one key per file touched (session baseline, cascade baseline, review-
36
+ // graph entity snapshots) and never shrink. Only the second shape grows with
37
+ // batch size, so only it gets a bound; the fixed vocabulary stays on the plain
38
+ // map, unbounded, because its cardinality is small and stable. Per-file
39
+ // session facts opt into `boundedSessionFacts` instead, reusing fileFacts'
40
+ // LRU-count-cap-and-report discipline rather than adding a third mechanism.
41
+ // No pin exemption here (unlike fileFacts): every current per-file session
42
+ // fact is read once near dispatch start and written once at dispatch end, so
43
+ // nothing re-reads its OWN key later in the same dispatch the way a runner
44
+ // re-reads `file.content` — an eviction mid-batch only means the next dispatch
45
+ // of that path sees no previous baseline, the same safe state as its first
46
+ // ever dispatch this session.
47
+ //
48
+ // That equivalence holds only where an absent baseline means "report
49
+ // everything", which is true for the diagnostic baselines and false for the
50
+ // review-graph entity snapshot: there, an absent snapshot read as an empty one
51
+ // puts every symbol in `added` and drives a blast-radius run for a file that
52
+ // did not change. So an eviction leaves a tombstone, and a reader that needs
53
+ // the distinction asks `wasBoundedSessionFactEvicted`. Tombstones are keys
54
+ // only, and carry the same cap, so the coldest of them fall off in turn and
55
+ // that key reverts to first-dispatch semantics.
56
+ //
57
+ // Four per-file keys are minted per dispatched file today (diagnostic
58
+ // baseline, cascade baseline, entity snapshot, changed symbols), so 4096
59
+ // records covers roughly 1024 distinct files before the coldest file's
60
+ // baseline starts degrading.
61
+ const MAX_SESSION_FACT_RECORDS = 4096;
20
62
  export class FactStore {
21
63
  subject;
22
64
  // Insertion order is eviction order: the oldest-used record is evicted first.
23
65
  fileFacts = new Map();
24
66
  sessionFacts = new Map();
67
+ // Bounded sibling of `sessionFacts` for per-file-keyed session facts (#2282).
68
+ // True LRU: every fetch (get or create, see getBoundedSessionFact) refreshes
69
+ // recency, so the oldest-UNUSED record is evicted first, not merely the
70
+ // oldest-inserted.
71
+ boundedSessionFacts = new BoundedLruCache(MAX_SESSION_FACT_RECORDS);
72
+ // Keys evicted from `boundedSessionFacts` and not written since, so a reader
73
+ // can tell "evicted" from "never seen" (#2282). Same cap, same FIFO order.
74
+ evictedSessionFactKeys = new Set();
25
75
  // Pin refcount per file. A file is exempt from capacity eviction while its
26
76
  // count is > 0. Refcounted, not a Set, so two overlapping dispatches of the
27
77
  // same file both hold the pin until BOTH settle (#2243 item 2).
@@ -269,10 +319,57 @@ export class FactStore {
269
319
  hasSessionFact(factId) {
270
320
  return this.sessionFacts.has(factId);
271
321
  }
322
+ /** Bounded counterpart to {@link getSessionFact} for per-file-keyed session
323
+ * facts (#2282) — session baselines, cascade baselines, review-graph entity
324
+ * snapshots. LRU touch: a read moves the record off the eviction end. */
325
+ getBoundedSessionFact(factId) {
326
+ if (!this.boundedSessionFacts.has(factId))
327
+ return undefined;
328
+ return this.boundedSessionFacts.get(factId);
329
+ }
330
+ /** Bounded counterpart to {@link setSessionFact}. Callers use this instead
331
+ * of `setSessionFact` for any family that mints one key per file/entity
332
+ * touched, so the store's count stays bounded across a large batch instead
333
+ * of retaining one entry per distinct path for the process lifetime. */
334
+ setBoundedSessionFact(factId, value) {
335
+ this.evictedSessionFactKeys.delete(factId);
336
+ const evicted = this.boundedSessionFacts.set(factId, value);
337
+ for (const [oldestKey] of evicted) {
338
+ this.evictedSessionFactKeys.add(oldestKey);
339
+ while (this.evictedSessionFactKeys.size > MAX_SESSION_FACT_RECORDS) {
340
+ const oldestTombstone = this.evictedSessionFactKeys
341
+ .values()
342
+ .next().value;
343
+ if (oldestTombstone === undefined)
344
+ break;
345
+ this.evictedSessionFactKeys.delete(oldestTombstone);
346
+ }
347
+ capacityEvictionReporter?.(this.subject, "session-count", `session-fact store axis=count exceeded ${MAX_SESSION_FACT_RECORDS} records; evicted least-recently-used fact for ${oldestKey}`);
348
+ }
349
+ }
350
+ hasBoundedSessionFact(factId) {
351
+ return this.boundedSessionFacts.has(factId);
352
+ }
353
+ /** True when this key held a bounded session fact that capacity eviction
354
+ * dropped and nothing has rewritten since (#2282). Readers whose "absent"
355
+ * branch is not a safe default — the review-graph entity snapshot, where
356
+ * absent would read as "every symbol is new" — use this to tell an evicted
357
+ * key from one this session has never seen. */
358
+ wasBoundedSessionFactEvicted(factId) {
359
+ return this.evictedSessionFactKeys.has(factId);
360
+ }
361
+ /** O(1) entry count for memory-attribution sampling (#2282 Observability):
362
+ * the fixed-vocabulary map plus the bounded per-file map, so a caller gets
363
+ * this store's whole `sessionFacts` footprint in one number. */
364
+ getSessionFactEntryCount() {
365
+ return this.sessionFacts.size + this.boundedSessionFacts.size;
366
+ }
272
367
  /** Call on session reset only. Clears everything including tool cache and baselines. */
273
368
  clearAll() {
274
369
  this.fileFacts.clear();
275
370
  this.sessionFacts.clear();
371
+ this.boundedSessionFacts.clear();
372
+ this.evictedSessionFactKeys.clear();
276
373
  this.pinnedFiles.clear();
277
374
  this.retainedContentBytes = 0;
278
375
  this.pinnedContentBytesTotal = 0;
@@ -139,7 +139,6 @@ setFactStoreEvictionReporter((subject, axis, reason) => {
139
139
  reason,
140
140
  });
141
141
  });
142
- const cascadeDiagnosticBaselines = new Map();
143
142
  const sessionRunnerRegistry = new RunnerRegistry();
144
143
  registerDefaultRunners(sessionRunnerRegistry);
145
144
  const LSP_CAPABLE_KINDS = new Set(getLspCapableKinds());
@@ -385,7 +384,6 @@ export function resetDispatchBaselines(cwd) {
385
384
  clearModuleGraphCache();
386
385
  recentlyCleanNeighborCache.clear();
387
386
  primaryFilesThisTurn.clear();
388
- cascadeDiagnosticBaselines.clear();
389
387
  cascadeSessionStats = {
390
388
  runs: 0,
391
389
  diagnosticsSurfaced: 0,
@@ -405,10 +403,16 @@ export function getCascadeSessionStats() {
405
403
  }
406
404
  const recentlyCleanNeighborCache = new Map();
407
405
  /** O(1) entry count of this module's turn-bounded cache (#1123 item 2
408
- * memory attribution) — a `Map.size` read, never iterated. */
406
+ * memory attribution) — a `Map.size` read, never iterated.
407
+ * `sessionFactEntries` (#2282) is the dispatch `FactStore`'s own
408
+ * `sessionFacts` footprint: the fixed-vocabulary map (small, unbounded by
409
+ * design) plus the bounded per-file map (capped at `MAX_SESSION_FACT_RECORDS`
410
+ * — see `fact-store.ts`), so this number is now itself bounded rather than
411
+ * invisible growth. */
409
412
  export function getDispatchCascadeCacheStats() {
410
413
  return {
411
414
  recentlyCleanNeighborCacheSize: recentlyCleanNeighborCache.size,
415
+ sessionFactEntries: sessionFacts.getSessionFactEntryCount(),
412
416
  };
413
417
  }
414
418
  const RECENTLY_CLEAN_TTL_TURNS = 5;
@@ -1940,10 +1944,8 @@ function diagnosticDeltaKey(diagnostic) {
1940
1944
  function applyCascadeDeltaBaselines(neighbors) {
1941
1945
  return neighbors.map((neighbor) => {
1942
1946
  const baselineKey = `session.baseline.cascade.${normalizeMapKey(neighbor.filePath)}`;
1943
- const previous = cascadeDiagnosticBaselines.get(baselineKey) ??
1944
- sessionFacts.getSessionFact(baselineKey);
1945
- cascadeDiagnosticBaselines.set(baselineKey, [...neighbor.diagnostics]);
1946
- sessionFacts.setSessionFact(baselineKey, [...neighbor.diagnostics]);
1947
+ const previous = sessionFacts.getBoundedSessionFact(baselineKey);
1948
+ sessionFacts.setBoundedSessionFact(baselineKey, [...neighbor.diagnostics]);
1947
1949
  if (!previous)
1948
1950
  return neighbor;
1949
1951
  const before = new Set(previous.map(diagnosticDeltaKey));
@@ -61,7 +61,6 @@ const actionlintRunner = {
61
61
  id: "actionlint",
62
62
  appliesTo: ["yaml"],
63
63
  priority: PRIORITY.YAML_LINT + 1,
64
- enabledByDefault: true,
65
64
  skipTestFiles: false,
66
65
  when(ctx) {
67
66
  return isGitHubWorkflowFile(ctx.filePath);