@herbertgao/pi-extensions 2026.8.3 → 2026.8.5

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 (408) hide show
  1. package/README.md +45 -4
  2. package/examples/pi-footer.json +275 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +10 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.md +10 -2
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +5 -8
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
  14. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  15. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
  16. package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
  17. package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
  18. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
  19. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +15 -2
  21. package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
  22. package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
  25. package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
  26. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
  27. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  28. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
  29. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
  30. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
  31. package/node_modules/@narumitw/pi-btw/README.md +8 -7
  32. package/node_modules/@narumitw/pi-btw/package.json +2 -2
  33. package/node_modules/@narumitw/pi-btw/src/menu.ts +1 -0
  34. package/node_modules/pi-footer/CHANGELOG.md +145 -0
  35. package/node_modules/pi-footer/LICENSE +21 -0
  36. package/node_modules/pi-footer/README.md +354 -0
  37. package/node_modules/pi-footer/package.json +68 -0
  38. package/node_modules/pi-footer/src/cache.ts +106 -0
  39. package/node_modules/pi-footer/src/colors.ts +237 -0
  40. package/node_modules/pi-footer/src/config.ts +202 -0
  41. package/node_modules/pi-footer/src/event-widgets.ts +41 -0
  42. package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
  43. package/node_modules/pi-footer/src/git.ts +135 -0
  44. package/node_modules/pi-footer/src/index.ts +268 -0
  45. package/node_modules/pi-footer/src/metrics.ts +141 -0
  46. package/node_modules/pi-footer/src/presets.ts +383 -0
  47. package/node_modules/pi-footer/src/render.ts +114 -0
  48. package/node_modules/pi-footer/src/separators.ts +52 -0
  49. package/node_modules/pi-footer/src/types.ts +122 -0
  50. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
  51. package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
  52. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
  53. package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
  54. package/node_modules/pi-footer/src/ui/events.ts +35 -0
  55. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
  56. package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
  57. package/node_modules/pi-footer/src/ui/fields.ts +252 -0
  58. package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
  59. package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
  60. package/node_modules/pi-footer/src/ui/layout.ts +17 -0
  61. package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
  62. package/node_modules/pi-footer/src/ui/model.ts +64 -0
  63. package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
  64. package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
  65. package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
  66. package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
  67. package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
  68. package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
  69. package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
  70. package/node_modules/pi-footer/src/ui/screen.ts +243 -0
  71. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
  72. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
  73. package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
  74. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
  75. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
  76. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
  77. package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
  78. package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
  79. package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
  80. package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
  81. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
  82. package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
  83. package/node_modules/pi-footer/src/ui/theme.ts +48 -0
  84. package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
  85. package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
  86. package/node_modules/pi-footer/src/ui.ts +66 -0
  87. package/node_modules/pi-footer/src/widgets/context.ts +28 -0
  88. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
  89. package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
  90. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
  91. package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
  92. package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
  93. package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
  94. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
  95. package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
  96. package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
  97. package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
  98. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
  99. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
  100. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
  101. package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
  102. package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
  103. package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
  104. package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
  105. package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
  106. package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
  107. package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
  108. package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
  109. package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
  110. package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
  111. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
  112. package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
  113. package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
  114. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
  115. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
  116. package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
  117. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
  118. package/node_modules/pi-footer/src/widgets/options.ts +122 -0
  119. package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
  120. package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
  121. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
  122. package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
  123. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
  124. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
  125. package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
  126. package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
  127. package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
  128. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
  129. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
  130. package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
  131. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
  132. package/node_modules/pi-footer/src/widgets/store.ts +26 -0
  133. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
  134. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
  135. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
  136. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
  137. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
  138. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
  139. package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
  140. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
  141. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
  142. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
  143. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
  144. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
  145. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
  146. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
  147. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
  148. package/node_modules/pi-footer/src/widgets/types.ts +181 -0
  149. package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
  150. package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
  151. package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
  152. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
  153. package/node_modules/pi-lens/CHANGELOG.md +2440 -954
  154. package/node_modules/pi-lens/README.md +13 -0
  155. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
  156. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
  157. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
  158. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
  159. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
  160. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
  161. package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
  162. package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
  163. package/node_modules/pi-lens/dist/clients/biome-client.js +29 -25
  164. package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
  165. package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
  166. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
  167. package/node_modules/pi-lens/dist/clients/bus-publish.js +10 -3
  168. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
  169. package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
  170. package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
  171. package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
  172. package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
  173. package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
  174. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
  175. package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
  176. package/node_modules/pi-lens/dist/clients/console-guard-install.js +14 -0
  177. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
  178. package/node_modules/pi-lens/dist/clients/dead-code-client.js +2 -1
  179. package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
  180. package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
  181. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
  182. package/node_modules/pi-lens/dist/clients/dependency-checker.js +347 -75
  183. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +61 -11
  184. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
  185. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +63 -20
  186. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
  187. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
  188. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
  189. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
  190. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
  191. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1085 -681
  192. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
  193. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
  194. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
  195. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
  196. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
  197. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
  198. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
  199. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  200. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
  201. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
  202. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
  203. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +14 -6
  204. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
  205. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
  206. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
  207. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
  208. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
  209. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  210. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  211. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
  212. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
  213. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
  214. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
  215. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
  216. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +277 -26
  217. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
  218. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
  219. package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
  220. package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
  221. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
  222. package/node_modules/pi-lens/dist/clients/extension-log.js +139 -0
  223. package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
  224. package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
  225. package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
  226. package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
  227. package/node_modules/pi-lens/dist/clients/format-events-publish.js +16 -3
  228. package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
  229. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
  230. package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
  231. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
  232. package/node_modules/pi-lens/dist/clients/git-guard.js +681 -11
  233. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
  234. package/node_modules/pi-lens/dist/clients/go-client.js +2 -1
  235. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +8 -0
  236. package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
  237. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
  238. package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
  239. package/node_modules/pi-lens/dist/clients/installer/index.js +390 -99
  240. package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
  241. package/node_modules/pi-lens/dist/clients/jscpd-client.js +31 -54
  242. package/node_modules/pi-lens/dist/clients/knip-client.js +15 -36
  243. package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
  244. package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
  245. package/node_modules/pi-lens/dist/clients/latency-logger.js +23 -1
  246. package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
  247. package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
  248. package/node_modules/pi-lens/dist/clients/lens-events.js +27 -4
  249. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  250. package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
  251. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +30 -0
  252. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
  253. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +1 -1
  254. package/node_modules/pi-lens/dist/clients/lsp/client.js +493 -48
  255. package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
  256. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +86 -0
  257. package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
  258. package/node_modules/pi-lens/dist/clients/lsp/index.js +1807 -780
  259. package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
  260. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  261. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
  262. package/node_modules/pi-lens/dist/clients/lsp/server.js +196 -32
  263. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
  264. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
  265. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
  266. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +123 -32
  267. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
  268. package/node_modules/pi-lens/dist/clients/mcp/session.js +216 -8
  269. package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
  270. package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
  271. package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
  272. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
  273. package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
  274. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
  275. package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
  276. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
  277. package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
  278. package/node_modules/pi-lens/dist/clients/pipeline.js +47 -13
  279. package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
  280. package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
  281. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
  282. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
  283. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
  284. package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
  285. package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
  286. package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
  287. package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
  288. package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
  289. package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
  290. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
  291. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
  292. package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
  293. package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
  294. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
  295. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
  296. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
  297. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
  298. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
  299. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
  300. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
  301. package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
  302. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +107 -73
  303. package/node_modules/pi-lens/dist/clients/runtime-context.js +36 -12
  304. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +74 -6
  305. package/node_modules/pi-lens/dist/clients/runtime-session.js +405 -117
  306. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
  307. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +218 -23
  308. package/node_modules/pi-lens/dist/clients/runtime-turn.js +237 -64
  309. package/node_modules/pi-lens/dist/clients/rust-client.js +2 -1
  310. package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
  311. package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -1
  312. package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
  313. package/node_modules/pi-lens/dist/clients/sg-runner.js +284 -174
  314. package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
  315. package/node_modules/pi-lens/dist/clients/smells-rollup.js +224 -0
  316. package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
  317. package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
  318. package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
  319. package/node_modules/pi-lens/dist/clients/startup-timing.js +1 -1
  320. package/node_modules/pi-lens/dist/clients/test-runner-client.js +38 -8
  321. package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
  322. package/node_modules/pi-lens/dist/clients/tool-policy.js +388 -39
  323. package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
  324. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
  325. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
  326. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
  327. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
  328. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
  329. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
  330. package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
  331. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
  332. package/node_modules/pi-lens/dist/clients/warm-attach.js +33 -13
  333. package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
  334. package/node_modules/pi-lens/dist/clients/word-index.js +391 -64
  335. package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
  336. package/node_modules/pi-lens/dist/index.js +49361 -36888
  337. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
  338. package/node_modules/pi-lens/dist/mcp/server.js +211 -44
  339. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
  340. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +200 -36
  341. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +153 -40
  342. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
  343. package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
  344. package/node_modules/pi-lens/docs/agent-guide.md +2 -2
  345. package/node_modules/pi-lens/docs/agent-tools.md +21 -10
  346. package/node_modules/pi-lens/docs/analysisall.md +192 -0
  347. package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
  348. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +5 -2
  349. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
  350. package/node_modules/pi-lens/docs/environment-variables.md +44 -0
  351. package/node_modules/pi-lens/docs/fable.md +27 -0
  352. package/node_modules/pi-lens/docs/features.md +31 -2
  353. package/node_modules/pi-lens/docs/globalconfig.md +45 -1
  354. package/node_modules/pi-lens/docs/language-coverage.md +4 -3
  355. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
  356. package/node_modules/pi-lens/docs/mcp.md +37 -4
  357. package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
  358. package/node_modules/pi-lens/docs/settings.md +12 -1
  359. package/node_modules/pi-lens/docs/tools.md +4 -1
  360. package/node_modules/pi-lens/docs/usage.md +18 -0
  361. package/node_modules/pi-lens/package.json +10 -10
  362. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
  363. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  364. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
  365. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  366. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  367. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
  368. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
  369. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
  370. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
  371. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
  372. package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
  373. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
  374. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +55 -2
  375. package/node_modules/pi-mcp-adapter/CHANGELOG.md +25 -0
  376. package/node_modules/pi-mcp-adapter/README.md +34 -3
  377. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
  378. package/node_modules/pi-mcp-adapter/commands.ts +15 -7
  379. package/node_modules/pi-mcp-adapter/direct-tools.ts +54 -7
  380. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
  381. package/node_modules/pi-mcp-adapter/index.ts +8 -3
  382. package/node_modules/pi-mcp-adapter/init.ts +29 -5
  383. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
  384. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
  385. package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
  386. package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
  387. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
  388. package/node_modules/pi-mcp-adapter/metadata-cache.ts +27 -4
  389. package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
  390. package/node_modules/pi-mcp-adapter/package.json +3 -3
  391. package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
  392. package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
  393. package/node_modules/pi-mcp-adapter/server-manager.ts +36 -7
  394. package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
  395. package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
  396. package/node_modules/pi-mcp-adapter/tool-metadata.ts +42 -4
  397. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
  398. package/node_modules/pi-mcp-adapter/types.ts +93 -27
  399. package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
  400. package/package.json +17 -13
  401. package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
  402. package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
  403. package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
  404. package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
  405. package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
  406. package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
  407. package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
  408. package/node_modules/pi-lens/dist/clients/types.js +0 -11
@@ -24,13 +24,14 @@ import * as path from "node:path";
24
24
  import { fileURLToPath } from "node:url";
25
25
  import { AstGrepClient } from "../clients/ast-grep-client.js";
26
26
  import { CacheManager } from "../clients/cache-manager.js";
27
- import { computeBuildStamp, STALE_SERVED_BY_FRESH, STALE_WARN_ONLY, StalenessGate, stalenessCheckEnabled, } from "./build-staleness.js";
28
- import { analyzeFile, analyzeFileFresh, canRebuildPiLens, createMcpHost, diagnosticStats, ensureLspConfig, ipcPathForCwd, lspStatus, renderLspBrokenStatusLines, moduleReport, projectReport, projectScan, readEnclosing, readSymbol, recentLatency, renderCompactModuleReport, renderCompactProjectReport, resolveRebuildScript, resourceFootprint, runRebuild, runSessionStart, runTurnEnd, scanTruncationNotice, summarizeScan, symbolSearch, treeSitterRuntimeStatus, } from "../clients/lens-engine.js";
27
+ import { getDegradationSummary, renderDegradationLines, } from "../clients/degradation-ledger.js";
28
+ import { acknowledgeTurnEnd, analyzeFile, analyzeFileFresh, canRebuildPiLens, createMcpHost, createWarmIpcLineReader, createWarmIpcRequestQueue, diagnosticStats, ensureLspConfig, generatedSkipNotice, ipcPathForCwd, lspStatus, moduleReport, projectReport, projectScan, readEnclosing, readSymbol, readTurnEndStatus, recentLatency, renderCompactModuleReport, renderCompactProjectReport, renderLspBrokenStatusLines, resolveRebuildScript, resourceFootprint, runRebuild, runSessionStart, runTurnEnd, runTurnEndForIpc, scanTruncationNotice, summarizeScan, symbolSearch, treeSitterRuntimeStatus, WARM_TURN_END_SCHEMA_VERSION, } from "../clients/lens-engine.js";
29
29
  import { createAstGrepReplaceTool } from "../tools/ast-grep-replace.js";
30
30
  import { createAstGrepSearchTool } from "../tools/ast-grep-search.js";
31
31
  import { createLensDiagnosticsTool } from "../tools/lens-diagnostics.js";
32
32
  import { createLspDiagnosticsTool } from "../tools/lsp-diagnostics.js";
33
33
  import { createLspNavigationTool } from "../tools/lsp-navigation.js";
34
+ import { computeBuildStamp, STALE_SERVED_BY_FRESH, STALE_WARN_ONLY, StalenessGate, stalenessCheckEnabled, } from "./build-staleness.js";
34
35
  // Any stray stdout write corrupts the JSON-RPC stream; force it onto stderr.
35
36
  console.log = (...args) => {
36
37
  console.error(...args);
@@ -191,6 +192,32 @@ function getAutoSessionStatus() {
191
192
  // runs in THIS warm process (LSP-complete) instead of a cold hook process.
192
193
  // Responses go over the socket — never stdout — so the MCP stream is untouched.
193
194
  const IPC_PATH = ipcPathForCwd(DEFAULT_CWD);
195
+ /**
196
+ * #1273: the turn-end route runs the TARGET directory's configured test runner
197
+ * and spins up an LSP for it, from a client-supplied `cwd`. Every legitimate
198
+ * client derived the socket path from that same cwd, so a workspace check costs
199
+ * nothing legitimate — but without it, anything that can reach this endpoint
200
+ * (same-uid processes, a permissive-umask shared host, a Windows named pipe's
201
+ * more generous default DACL) can make the server execute an arbitrary
202
+ * directory's test suite. "Lint one file" and "run this directory's test suite"
203
+ * are different blast radii, so the guard is on turn-end and its ack.
204
+ */
205
+ function rejectForeignTurnCwd(route, cwd) {
206
+ const message = `${route} cwd outside this server's workspace: ${path.resolve(cwd)} not within ${DEFAULT_CWD}`;
207
+ console.error(`[pi-lens-mcp] rejected ${message}`);
208
+ return message;
209
+ }
210
+ function isWithinServerWorkspace(cwd) {
211
+ const target = path.resolve(cwd);
212
+ // `path.relative` applies the platform's own path semantics (including
213
+ // win32 case-insensitivity), which is what "inside the workspace" means
214
+ // here — do NOT hand-roll a case fold. An empty result means `target`
215
+ // IS `DEFAULT_CWD` (win32 can reach that via a pure case/drive-letter
216
+ // difference, since path.relative there is case-insensitive) and must
217
+ // be accepted, not rejected — do NOT reintroduce a `rel !== ""` guard.
218
+ const rel = path.relative(DEFAULT_CWD, target);
219
+ return !rel.startsWith("..") && !path.isAbsolute(rel);
220
+ }
194
221
  function startIpcServer() {
195
222
  // POSIX: a stale socket file blocks listen; remove it first. (Named pipes on
196
223
  // Windows don't need this.)
@@ -202,33 +229,77 @@ function startIpcServer() {
202
229
  // no stale socket — fine
203
230
  }
204
231
  }
232
+ const requestQueue = createWarmIpcRequestQueue();
205
233
  const ipc = net.createServer((socket) => {
206
234
  socket.setEncoding("utf8");
207
- let buffer = "";
208
- socket.on("data", (chunk) => {
209
- buffer += chunk;
210
- const newline = buffer.indexOf("\n");
211
- if (newline === -1)
212
- return;
213
- const line = buffer.slice(0, newline);
214
- void (async () => {
235
+ // One-shot per connection (#1219): clients write exactly one request and
236
+ // read one reply, so a handler that kept re-reading the same buffered
237
+ // line re-dispatched the request on stray bytes. The reader consumes the
238
+ // line and ignores anything after it.
239
+ socket.on("data", createWarmIpcLineReader((line) => {
240
+ void requestQueue.enqueue(async () => {
215
241
  try {
216
- // #535: the PostToolUse hook bin (mcp/analyze-cli.ts) already treats
217
- // ANY error response as "no usable warm server" and falls back to
218
- // its own cold, load-fresh-from-disk analysis path — so on a stale
219
- // warm build, replying with an error IS the fresh-fork behavior for
220
- // this channel, for free. No separate fresh-fork plumbing needed
221
- // here: the client-side fallback already loads current code.
222
242
  if (isWarmBuildStale()) {
223
- console.error("[pi-lens-mcp] warm analyze: build stale, replying error so the hook falls back cold");
224
- socket.end(`${JSON.stringify({ error: "warm build stale — falling back to cold analysis" })}\n`);
243
+ console.error("[pi-lens-mcp] warm request: build stale, replying with an error");
244
+ socket.end(`${JSON.stringify({ error: "warm build stale" })}\n`);
245
+ return;
246
+ }
247
+ const parsed = JSON.parse(line);
248
+ if (parsed.route === "turn-end-ack") {
249
+ if (parsed.version !== WARM_TURN_END_SCHEMA_VERSION ||
250
+ typeof parsed.deliveryId !==
251
+ "string") {
252
+ socket.end(`${JSON.stringify({ error: `turn-end ack schema ${parsed.version} != ${WARM_TURN_END_SCHEMA_VERSION}` })}\n`);
253
+ return;
254
+ }
255
+ const turnCwd = parsed.cwd ?? DEFAULT_CWD;
256
+ if (!isWithinServerWorkspace(turnCwd)) {
257
+ socket.end(`${JSON.stringify({ error: rejectForeignTurnCwd("turn-end-ack", turnCwd) })}\n`);
258
+ return;
259
+ }
260
+ const acknowledged = acknowledgeTurnEnd(turnCwd, parsed.deliveryId);
261
+ socket.end(`${JSON.stringify({
262
+ result: {
263
+ route: "turn-end-ack",
264
+ version: WARM_TURN_END_SCHEMA_VERSION,
265
+ acknowledged,
266
+ },
267
+ })}\n`);
268
+ return;
269
+ }
270
+ if (parsed.route === "turn-end") {
271
+ if (parsed.version !== WARM_TURN_END_SCHEMA_VERSION) {
272
+ socket.end(`${JSON.stringify({ error: `turn-end schema ${parsed.version} != ${WARM_TURN_END_SCHEMA_VERSION}` })}\n`);
273
+ return;
274
+ }
275
+ const turnCwd = parsed.cwd ?? DEFAULT_CWD;
276
+ if (!isWithinServerWorkspace(turnCwd)) {
277
+ socket.end(`${JSON.stringify({ error: rejectForeignTurnCwd("turn-end", turnCwd) })}\n`);
278
+ return;
279
+ }
280
+ // #1274: a client that already gave up (hook timeout, killed
281
+ // Claude Code) leaves a destroyed socket. Starting a heavy
282
+ // pass whose reply nobody can read is pure waste; the findings
283
+ // stay in the cache for the next Stop either way.
284
+ if (socket.destroyed) {
285
+ console.error(`[pi-lens-mcp] warm turn-end: client gone before the pass started (${turnCwd})`);
286
+ return;
287
+ }
288
+ console.error(`[pi-lens-mcp] warm turn-end: ${turnCwd}`);
289
+ await ensureReady(turnCwd);
290
+ const delivery = await runTurnEndForIpc(turnCwd);
291
+ const result = {
292
+ route: "turn-end",
293
+ version: WARM_TURN_END_SCHEMA_VERSION,
294
+ turnEnd: delivery.outcome.turnEnd,
295
+ tests: delivery.outcome.tests,
296
+ deliveryId: delivery.deliveryId,
297
+ };
298
+ socket.end(`${JSON.stringify({ result })}\n`);
225
299
  return;
226
300
  }
227
- const req = JSON.parse(line);
301
+ const req = parsed;
228
302
  console.error(`[pi-lens-mcp] warm analyze: ${req.file}`);
229
- // Warm = full LSP + an edit-detection path (register turn-state) +
230
- // review-graph maintenance (#536 — this is an in-process, long-lived
231
- // path, unlike the ephemeral `fresh` worker).
232
303
  const result = await analyzeFile(req.file, req.cwd, {
233
304
  registerTurnState: true,
234
305
  updateGraph: true,
@@ -238,8 +309,8 @@ function startIpcServer() {
238
309
  catch (err) {
239
310
  socket.end(`${JSON.stringify({ error: String(err) })}\n`);
240
311
  }
241
- })();
242
- });
312
+ });
313
+ }));
243
314
  socket.on("error", () => socket.destroy());
244
315
  });
245
316
  ipc.on("error", (err) => {
@@ -395,7 +466,7 @@ const ALL_TOOLS = [
395
466
  },
396
467
  flags: {
397
468
  type: "object",
398
- description: "Optional pi-lens flag overrides for this run, e.g. {\"no-lsp\": true} to bench the non-LSP path.",
469
+ description: 'Optional pi-lens flag overrides for this run, e.g. {"no-lsp": true} to bench the non-LSP path.',
399
470
  },
400
471
  },
401
472
  required: ["file"],
@@ -415,8 +486,14 @@ const ALL_TOOLS = [
415
486
  inputSchema: {
416
487
  type: "object",
417
488
  properties: {
418
- limit: { type: "number", description: "Max reports to return (default 5)." },
419
- file: { type: "string", description: "Only reports whose path ends with this." },
489
+ limit: {
490
+ type: "number",
491
+ description: "Max reports to return (default 5).",
492
+ },
493
+ file: {
494
+ type: "string",
495
+ description: "Only reports whose path ends with this.",
496
+ },
420
497
  },
421
498
  },
422
499
  },
@@ -439,6 +516,13 @@ const ALL_TOOLS = [
439
516
  properties: {
440
517
  cwd: { type: "string" },
441
518
  maxFiles: { type: "number", description: "Cap files scanned." },
519
+ includeGenerated: {
520
+ type: "boolean",
521
+ description: "Scan WITHOUT the generated/artifact NAME-heuristic filter " +
522
+ "(lockfiles, gen.ts-style names, generated/ dirs, …). Default " +
523
+ "false. Use when a scan's 'excluded by generated-name " +
524
+ "heuristics' notice suggests a real file was skipped.",
525
+ },
442
526
  },
443
527
  },
444
528
  },
@@ -495,7 +579,9 @@ const ALL_TOOLS = [
495
579
  "(this path never calls LSP). `semantic.source` reports whether graph " +
496
580
  "data was used. Pass `blastRadius: true` for the cross-file blast radius " +
497
581
  "(transitive dependents as ranked file reads, read-only over the cached " +
498
- 'graph). `view: "compact"` returns a line-oriented text rendering ' +
582
+ "graph). Pass `callGraph: true` for bounded derived callers/callees; a " +
583
+ "cold or stale call-graph cache is reported explicitly, never as zero calls. " +
584
+ '`view: "compact"` returns a line-oriented text rendering ' +
499
585
  "(cheapest option) instead of JSON. An outline shows shape, not bodies.",
500
586
  inputSchema: {
501
587
  type: "object",
@@ -526,6 +612,14 @@ const ALL_TOOLS = [
526
612
  type: "number",
527
613
  description: "Max hops for the blast-radius walk (default 3). Only used with blastRadius.",
528
614
  },
615
+ callGraph: {
616
+ type: "boolean",
617
+ description: "Include bounded derived callers/callees from the cached FunctionCallGraph; cold or stale cache state is explicit.",
618
+ },
619
+ maxCallGraphEntries: {
620
+ type: "number",
621
+ description: "Per-direction cap for call-graph relations (default 20).",
622
+ },
529
623
  },
530
624
  required: ["file"],
531
625
  },
@@ -685,8 +779,11 @@ const ALL_TOOLS = [
685
779
  {
686
780
  name: "pilens_ast_grep_search",
687
781
  description: "Structural (AST) code search via ast-grep — match by code structure, not " +
688
- "text. Use meta-variables ($X) and AST context (e.g. 'console.log($MSG)', " +
689
- "'function $NAME() { $$$ }'). Far more precise than grep for code shapes.",
782
+ "text. Use complete patterns with arguments (e.g. 'console.log($MSG)', " +
783
+ "'function $NAME($$$ARGS) { $$$BODY }'), or use nodeKind to find every " +
784
+ "node of a known grammar kind. Metavariables do not match text inside " +
785
+ "quoted string literals; use an exact string or grep for wildcard text. " +
786
+ "This is the same schema and synthesis path as the pi tool.",
690
787
  inputSchema: schemaWithCwd(astGrepSearchTool.parameters),
691
788
  },
692
789
  {
@@ -739,7 +836,10 @@ async function callTool(name, args) {
739
836
  if (name === "pilens_analyze") {
740
837
  const file = args.file;
741
838
  if (typeof file !== "string" || file.length === 0) {
742
- return { ...toolText("pilens_analyze requires a 'file' string."), isError: true };
839
+ return {
840
+ ...toolText("pilens_analyze requires a 'file' string."),
841
+ isError: true,
842
+ };
743
843
  }
744
844
  const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
745
845
  const requestedMode = args.mode === "fresh" ? "fresh" : "warm";
@@ -814,7 +914,8 @@ async function callTool(name, args) {
814
914
  const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles)
815
915
  ? Math.max(1, Math.floor(args.maxFiles))
816
916
  : undefined;
817
- const snapshot = await projectScan(cwd, maxFiles);
917
+ const includeGenerated = args.includeGenerated === true;
918
+ const snapshot = await projectScan(cwd, maxFiles, includeGenerated);
818
919
  // #747: a cwd at/above $HOME refuses to walk — say so instead of letting
819
920
  // "Scanned 0 file(s) → 0 diagnostics" read as a clean project.
820
921
  if (snapshot.unsafeRoot) {
@@ -840,6 +941,11 @@ async function callTool(name, args) {
840
941
  const truncationNotice = scanTruncationNotice(snapshot);
841
942
  if (truncationNotice)
842
943
  summaryLines.push(truncationNotice);
944
+ // #1107 phase 2: same "reached the seam but nothing rendered it" gap as
945
+ // #784's scanTruncationNotice, for the generated-name skip counters.
946
+ const skipNotice = generatedSkipNotice(snapshot);
947
+ if (skipNotice)
948
+ summaryLines.push(skipNotice);
843
949
  return toolText(summaryLines.join("\n"), {
844
950
  filesScanned: snapshot.filesScanned,
845
951
  runners: snapshot.runners,
@@ -852,6 +958,15 @@ async function callTool(name, args) {
852
958
  ...(snapshot.treeSitterStatus
853
959
  ? { treeSitterStatus: snapshot.treeSitterStatus }
854
960
  : {}),
961
+ ...(snapshot.generatedFileSkips
962
+ ? { generatedFileSkips: snapshot.generatedFileSkips }
963
+ : {}),
964
+ ...(snapshot.generatedNameOnlySkips
965
+ ? { generatedNameOnlySkips: snapshot.generatedNameOnlySkips }
966
+ : {}),
967
+ ...(snapshot.generatedDirSkips
968
+ ? { generatedDirSkips: snapshot.generatedDirSkips }
969
+ : {}),
855
970
  });
856
971
  }
857
972
  if (name === "pilens_symbol_search") {
@@ -868,7 +983,8 @@ async function callTool(name, args) {
868
983
  const lang = typeof args.lang === "string" ? args.lang : undefined;
869
984
  const { available, results, hint, unavailableReason, coverage, snapshotGeneratedAt, } = await symbolSearch(query, cwd, limit, { paths, lang });
870
985
  if (!available) {
871
- return toolText(hint ?? "No word index for this workspace yet — run pilens_session_start first.", { available: false, query, hint, unavailableReason }, true);
986
+ return toolText(hint ??
987
+ "No word index for this workspace yet — run pilens_session_start first.", { available: false, query, hint, unavailableReason }, true);
872
988
  }
873
989
  const stalenessNote = graphStalenessNote(snapshotGeneratedAt, "Project snapshot");
874
990
  if (results.length === 0) {
@@ -934,12 +1050,21 @@ async function callTool(name, args) {
934
1050
  Number.isFinite(args.blastRadiusDepth)
935
1051
  ? Math.max(1, Math.floor(args.blastRadiusDepth))
936
1052
  : undefined;
937
- const view = args.view === "summary" || args.view === "compact" ? args.view : undefined;
1053
+ const callGraph = args.callGraph === true;
1054
+ const maxCallGraphEntries = typeof args.maxCallGraphEntries === "number" &&
1055
+ Number.isFinite(args.maxCallGraphEntries)
1056
+ ? Math.max(1, Math.floor(args.maxCallGraphEntries))
1057
+ : undefined;
1058
+ const view = args.view === "summary" || args.view === "compact"
1059
+ ? args.view
1060
+ : undefined;
938
1061
  const focus = typeof args.focus === "string" ? args.focus : undefined;
939
1062
  const report = await moduleReport(file, cwd, {
940
1063
  maxRefsPerSymbol,
941
1064
  blastRadius,
942
1065
  blastRadiusDepth,
1066
+ callGraph,
1067
+ maxCallGraphEntries,
943
1068
  view,
944
1069
  focus,
945
1070
  });
@@ -960,14 +1085,18 @@ async function callTool(name, args) {
960
1085
  content: [
961
1086
  {
962
1087
  type: "text",
963
- text: graphStaleness ? `${compactText}\n\n${graphStaleness}` : compactText,
1088
+ text: graphStaleness
1089
+ ? `${compactText}\n\n${graphStaleness}`
1090
+ : compactText,
964
1091
  },
965
1092
  ],
966
1093
  };
967
1094
  }
968
1095
  // Compact (unindented) JSON — matches the pi tool's mirror (#512); an
969
1096
  // agent parses this payload, it doesn't read it formatted.
970
- return toolText(summary, graphStaleness ? { ...report, graphStalenessNote: graphStaleness } : report, true);
1097
+ return toolText(summary, graphStaleness
1098
+ ? { ...report, graphStalenessNote: graphStaleness }
1099
+ : report, true);
971
1100
  }
972
1101
  if (name === "pilens_project_report") {
973
1102
  const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
@@ -992,7 +1121,9 @@ async function callTool(name, args) {
992
1121
  content: [
993
1122
  {
994
1123
  type: "text",
995
- text: graphStaleness ? `${compactText}\n\n${graphStaleness}` : compactText,
1124
+ text: graphStaleness
1125
+ ? `${compactText}\n\n${graphStaleness}`
1126
+ : compactText,
996
1127
  },
997
1128
  ],
998
1129
  };
@@ -1001,7 +1132,9 @@ async function callTool(name, args) {
1001
1132
  `${report.entryPoints?.length ?? 0} entry point(s), ` +
1002
1133
  `${report.riskHotspots?.length ?? 0} risk hotspot(s)` +
1003
1134
  (graphStaleness ? `\n\n${graphStaleness}` : "");
1004
- return toolText(summary, graphStaleness ? { ...report, graphStalenessNote: graphStaleness } : report, true);
1135
+ return toolText(summary, graphStaleness
1136
+ ? { ...report, graphStalenessNote: graphStaleness }
1137
+ : report, true);
1005
1138
  }
1006
1139
  if (name === "pilens_read_symbol") {
1007
1140
  const file = typeof args.file === "string" ? args.file : "";
@@ -1032,13 +1165,20 @@ async function callTool(name, args) {
1032
1165
  ? ` (${result.ambiguous.count} matches — returned the ${result.kind}; pass \`kind\` to disambiguate: ${result.ambiguous.kinds.join(", ")})`
1033
1166
  : "";
1034
1167
  const header = `${result.kind} ${result.name}${ambiguityNote}${sigSuffix} ${path.relative(cwd, result.path)}:${result.startLine}-${result.endLine}`;
1035
- return { content: [{ type: "text", text: `${header}\n\n${result.source ?? ""}` }] };
1168
+ return {
1169
+ content: [
1170
+ { type: "text", text: `${header}\n\n${result.source ?? ""}` },
1171
+ ],
1172
+ };
1036
1173
  }
1037
1174
  if (name === "pilens_read_enclosing") {
1038
1175
  const file = typeof args.file === "string" ? args.file : "";
1039
1176
  const line = typeof args.line === "number" ? args.line : Number.NaN;
1040
1177
  if (!file.trim() || !Number.isFinite(line)) {
1041
- return { ...toolText("Provide `file` and a numeric `line`."), isError: true };
1178
+ return {
1179
+ ...toolText("Provide `file` and a numeric `line`."),
1180
+ isError: true,
1181
+ };
1042
1182
  }
1043
1183
  const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
1044
1184
  const kinds = Array.isArray(args.kinds)
@@ -1082,7 +1222,11 @@ async function callTool(name, args) {
1082
1222
  ? `${result.startLine}-${result.endLine} (partial of ${result.enclosingStartLine}-${result.enclosingEndLine})`
1083
1223
  : `${result.startLine}-${result.endLine}`;
1084
1224
  const header = `${result.kind} ${result.name} ${path.relative(cwd, result.path)}:${range}`;
1085
- return { content: [{ type: "text", text: `${header}\n\n${result.source ?? ""}` }] };
1225
+ return {
1226
+ content: [
1227
+ { type: "text", text: `${header}\n\n${result.source ?? ""}` },
1228
+ ],
1229
+ };
1086
1230
  }
1087
1231
  if (name === "pilens_health") {
1088
1232
  const { aliveClients, servers, brokenServers } = lspStatus();
@@ -1090,6 +1234,13 @@ async function callTool(name, args) {
1090
1234
  const stats = diagnosticStats();
1091
1235
  const autoSession = getAutoSessionStatus();
1092
1236
  const treeSitter = treeSitterRuntimeStatus();
1237
+ const degradations = getDegradationSummary();
1238
+ // #1272, following the #544 precedent: the Stop hook is a separate,
1239
+ // short-lived process, so a turn-end it skipped left no trace here at all
1240
+ // — a dead integration looked exactly like a clean turn, forever. The
1241
+ // hook records its outcome per workspace; this is where it becomes
1242
+ // visible without `claude --debug` log spelunking.
1243
+ const turnEnd = readTurnEndStatus(DEFAULT_CWD) ?? null;
1093
1244
  // #620: best-effort — a footprint read failure must never break the rest
1094
1245
  // of pilens_health's (much older, more load-bearing) reporting.
1095
1246
  const footprint = await resourceFootprint().catch(() => null);
@@ -1098,8 +1249,12 @@ async function callTool(name, args) {
1098
1249
  ? `Tree-sitter: DEGRADED — WASM runtime aborted${treeSitter.abortedAt ? ` at ${treeSitter.abortedAt}` : ""}; restart this server to recover`
1099
1250
  : "Tree-sitter: available",
1100
1251
  `LSP: ${aliveClients} alive client(s)`,
1101
- ...servers.map((server) => ` ${server.connected ? "✓" : "✗"} ${server.serverId} (${server.root})`),
1252
+ ...servers.flatMap((server) => [
1253
+ ` ${server.connected ? "✓" : "✗"} ${server.serverId} (${server.root})`,
1254
+ ...server.pullFailureHistory.slice(-1).map((failure) => ` ⚠ diagnostics pull failed: ${failure.method}${failure.code !== undefined ? ` (${failure.code})` : ""} — ${failure.message.length > 200 ? `${failure.message.slice(0, 200)}…` : failure.message}`),
1255
+ ]),
1102
1256
  ...renderLspBrokenStatusLines(brokenServers),
1257
+ ...renderDegradationLines(degradations),
1103
1258
  last
1104
1259
  ? `Last dispatch: ${path.basename(last.filePath)} — ${last.totalDurationMs}ms, ${last.totalDiagnostics} diagnostic(s)`
1105
1260
  : "Last dispatch: none yet",
@@ -1107,6 +1262,11 @@ async function callTool(name, args) {
1107
1262
  autoSession
1108
1263
  ? `Auto session_start: ${autoSession.succeeded ? "succeeded" : autoSession.error ? "FAILED" : autoSession.attempted ? "in progress" : "not yet attempted"}${autoSession.firedAt ? ` (fired ${autoSession.firedAt})` : ""}${autoSession.error ? ` — ${autoSession.error}` : ""}`
1109
1264
  : "Auto session_start: disabled (PI_LENS_MCP_AUTO_SESSION not set)",
1265
+ turnEnd
1266
+ ? `Stop-hook turn-end: ${turnEnd.ran} ran · ${turnEnd.skipped} skipped` +
1267
+ `${turnEnd.lastRunAt ? ` (last ran ${turnEnd.lastRunAt})` : ""}` +
1268
+ `${turnEnd.lastSkipReason ? ` — last skip: ${turnEnd.lastSkipReason}${turnEnd.lastSkipAt ? ` at ${turnEnd.lastSkipAt}` : ""}` : ""}`
1269
+ : "Stop-hook turn-end: no activity recorded (hook not installed, or no Stop yet)",
1110
1270
  footprint
1111
1271
  ? `Resource footprint: ${footprint.instanceCount} pi-lens instance(s) · ` +
1112
1272
  `${(footprint.totalRssBytes / 1024 / 1024).toFixed(0)}MB RSS · ` +
@@ -1132,7 +1292,9 @@ async function callTool(name, args) {
1132
1292
  },
1133
1293
  autoSession,
1134
1294
  treeSitter,
1295
+ turnEnd,
1135
1296
  resourceFootprint: footprint,
1297
+ degradations,
1136
1298
  });
1137
1299
  }
1138
1300
  if (name === "pilens_diagnostics") {
@@ -1186,7 +1348,9 @@ async function callTool(name, args) {
1186
1348
  }
1187
1349
  if (name === "pilens_ast_grep_search" || name === "pilens_ast_grep_replace") {
1188
1350
  const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
1189
- const tool = name === "pilens_ast_grep_search" ? astGrepSearchTool : astGrepReplaceTool;
1351
+ const tool = name === "pilens_ast_grep_search"
1352
+ ? astGrepSearchTool
1353
+ : astGrepReplaceTool;
1190
1354
  const out = (await tool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
1191
1355
  return { content: out.content };
1192
1356
  }
@@ -1270,7 +1434,10 @@ function withStaleWarning(result) {
1270
1434
  ...result,
1271
1435
  content: [
1272
1436
  ...result.content.slice(0, -1),
1273
- { ...last, text: `${last.text}\n\nwarmCodeStale: true\n${STALE_WARN_ONLY}` },
1437
+ {
1438
+ ...last,
1439
+ text: `${last.text}\n\nwarmCodeStale: true\n${STALE_WARN_ONLY}`,
1440
+ },
1274
1441
  ],
1275
1442
  };
1276
1443
  }