@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
@@ -53,6 +53,27 @@ export function logTreeSitterCacheStats(options) {
53
53
  },
54
54
  });
55
55
  }
56
+ /**
57
+ * The tree-sitter stack's terminal-safe diagnostic sink (#1333).
58
+ *
59
+ * pi owns the terminal, so nothing under `clients/` may `console.error`. The
60
+ * tree-sitter subsystem already owns `tree-sitter.log`, so its diagnostics stay
61
+ * there rather than moving to the generic `extension.log` — one log per
62
+ * subsystem, per the AGENTS.md logger invariant.
63
+ *
64
+ * `filePath` is optional because several of these fire process-wide (WASM
65
+ * abort, grammar fetch, rule compile) with no file in hand.
66
+ */
67
+ export function logTreeSitterDiagnostic(entry) {
68
+ logTreeSitter({
69
+ phase: "diagnostic",
70
+ filePath: entry.filePath ?? "<tree-sitter>",
71
+ ...(entry.languageId ? { languageId: entry.languageId } : {}),
72
+ status: entry.level ?? "error",
73
+ reason: entry.message,
74
+ metadata: { subsystem: entry.subsystem, ...(entry.metadata ?? {}) },
75
+ });
76
+ }
56
77
  export function getTreeSitterLogPath() {
57
78
  return TREE_SITTER_LOG_FILE;
58
79
  }
@@ -4,6 +4,7 @@
4
4
  * Loads tree-sitter queries from YAML files in rules/tree-sitter-queries/
5
5
  * and provides them to the TreeSitterClient.
6
6
  */
7
+ import { logTreeSitterDiagnostic } from "./tree-sitter-logger.js";
7
8
  import * as fs from "node:fs";
8
9
  import * as path from "node:path";
9
10
  import { resolvePackagePath } from "./package-root.js";
@@ -110,7 +111,12 @@ export class TreeSitterQueryLoader {
110
111
  /** Debug logging helper */
111
112
  dbg(msg) {
112
113
  if (this.verbose) {
113
- console.error(`[query-loader] ${msg}`);
114
+ // #1333: verbose gate preserved, sink moved to tree-sitter.log.
115
+ logTreeSitterDiagnostic({
116
+ subsystem: "query-loader",
117
+ level: "debug",
118
+ message: msg,
119
+ });
114
120
  }
115
121
  }
116
122
  /**
@@ -13,6 +13,7 @@
13
13
  * consumer skips further tree-sitter work (previously only the runner tracked this,
14
14
  * while the other subsystems kept calling the dead runtime).
15
15
  */
16
+ import { notifyUserDegradation } from "./user-notify.js";
16
17
  import * as path from "node:path";
17
18
  import { TreeSitterClient, } from "./tree-sitter-client.js";
18
19
  import { logTreeSitter } from "./tree-sitter-logger.js";
@@ -48,8 +49,12 @@ export function markTreeSitterWasmAborted() {
48
49
  _wasmAborted = true;
49
50
  _wasmAbortedAt = new Date().toISOString();
50
51
  _shared = null;
51
- console.error("[pi-lens] tree-sitter WASM runtime aborted; structural analysis is disabled " +
52
- "for this process. Restart the pi-lens extension/MCP server to recover.");
52
+ // HUMAN-audience: structural analysis is dead for the rest of the process
53
+ // and only a restart recovers it. Reaches the user through the HOST's
54
+ // render path (#1333); the machine-readable record is the logTreeSitter
55
+ // `runtime_abort` entry below.
56
+ notifyUserDegradation("pi-lens: tree-sitter WASM runtime aborted; structural analysis is disabled " +
57
+ "for this process. Restart the pi-lens extension/MCP server to recover.", "error");
53
58
  logTreeSitter({
54
59
  phase: "runtime_abort",
55
60
  filePath: process.cwd(),
@@ -2,6 +2,7 @@
2
2
  * Symbol extraction via tree-sitter queries
3
3
  * Extracts definitions and references from source files
4
4
  */
5
+ import { logTreeSitterDiagnostic } from "./tree-sitter-logger.js";
5
6
  import * as path from "node:path";
6
7
  import { loadWebTreeSitter } from "./deps/web-tree-sitter.js";
7
8
  // Tree-sitter query patterns for symbol extraction
@@ -505,6 +506,10 @@ SYMBOL_QUERIES.javascript = {
505
506
  constructor: (identifier) @newIdent) @newRef
506
507
  `,
507
508
  };
509
+ /** Language keys with symbol queries; used by fixture drift guards. */
510
+ export function getSymbolQueryLanguages() {
511
+ return Object.keys(SYMBOL_QUERIES);
512
+ }
508
513
  // Per-language import-source extraction (#249). Optional and independent of
509
514
  // SYMBOL_QUERIES: a language without an entry simply yields no imports (its
510
515
  // symbols still extract). Each query captures the import source text as
@@ -653,7 +658,11 @@ export class TreeSitterSymbolExtractor {
653
658
  }
654
659
  catch (err) {
655
660
  this.client.reportWasmAbort(err);
656
- console.error(`[symbol-extractor] Failed to init ${this.languageId}:`, err);
661
+ logTreeSitterDiagnostic({
662
+ subsystem: "symbol-extractor",
663
+ languageId: this.languageId,
664
+ message: `Failed to init ${this.languageId}: ${err instanceof Error ? err.message : String(err)}`,
665
+ });
657
666
  return false;
658
667
  }
659
668
  }
@@ -665,7 +674,12 @@ export class TreeSitterSymbolExtractor {
665
674
  catch (err) {
666
675
  if (this.client.reportWasmAbort(err))
667
676
  throw err;
668
- console.error(`[symbol-extractor] ${this.languageId} ${label} query failed: ${err.message}`);
677
+ logTreeSitterDiagnostic({
678
+ subsystem: "symbol-extractor",
679
+ languageId: this.languageId,
680
+ message: `${this.languageId} ${label} query failed: ${err.message}`,
681
+ metadata: { query: label },
682
+ });
669
683
  return null;
670
684
  }
671
685
  }
@@ -704,7 +718,16 @@ export class TreeSitterSymbolExtractor {
704
718
  imports.push(ref);
705
719
  }
706
720
  }
707
- return { symbols, refs, imports };
721
+ return {
722
+ symbols,
723
+ refs,
724
+ imports,
725
+ coverage: {
726
+ definitions: this.defQuery ? "complete" : "unavailable",
727
+ references: this.refQuery ? "complete" : "unavailable",
728
+ imports: this.importQuery ? "complete" : "unavailable",
729
+ },
730
+ };
708
731
  }
709
732
  queryMatches(query, rootNode) {
710
733
  try {
@@ -1001,26 +1024,40 @@ export class TreeSitterSymbolExtractor {
1001
1024
  parseRefMatch(match, filePath) {
1002
1025
  let name;
1003
1026
  let refNode;
1027
+ let referenceKind = "unknown";
1004
1028
  for (const capture of match.captures) {
1005
- if (capture.name.endsWith("Ident") ||
1006
- capture.name.endsWith("Method") ||
1007
- capture.name.endsWith("Field")) {
1029
+ const captureName = String(capture.name);
1030
+ if (captureName.endsWith("Ident") ||
1031
+ captureName.endsWith("Method") ||
1032
+ captureName.endsWith("Field")) {
1008
1033
  name = capture.node.text;
1009
1034
  // biome-ignore lint/suspicious/noExplicitAny: Node type
1010
1035
  refNode = capture.node;
1036
+ if (captureName.startsWith("type"))
1037
+ referenceKind = "type";
1038
+ else if (captureName.startsWith("call") || captureName.startsWith("new")) {
1039
+ referenceKind = "call";
1040
+ }
1011
1041
  }
1012
- if (capture.name.endsWith("Ref") && !refNode) {
1042
+ if (captureName.endsWith("Ref") && !refNode) {
1013
1043
  // biome-ignore lint/suspicious/noExplicitAny: Node type
1014
1044
  refNode = capture.node;
1045
+ if (captureName.startsWith("type"))
1046
+ referenceKind = "type";
1047
+ else if (captureName.startsWith("call") || captureName.startsWith("new")) {
1048
+ referenceKind = "call";
1049
+ }
1015
1050
  }
1016
1051
  }
1017
1052
  if (!name || !refNode)
1018
1053
  return null;
1019
1054
  return {
1020
1055
  symbolId: `${filePath}:${name}`, // Will be resolved later
1056
+ symbolName: name,
1021
1057
  filePath,
1022
1058
  line: refNode.startPosition.row + 1,
1023
1059
  column: refNode.startPosition.column + 1,
1060
+ referenceKind,
1024
1061
  };
1025
1062
  }
1026
1063
  // biome-ignore lint/suspicious/noExplicitAny: Node type
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The HUMAN channel for degradations discovered deep in `clients/` (#1333).
3
+ *
4
+ * Most of what the migrated `console.*` sites emitted is LOG-audience and
5
+ * belongs in an ndjson sink (`clients/extension-log.ts`). A small set is
6
+ * genuinely user-facing — "the config file you wrote is being ignored", "this
7
+ * language's grammar could not be fetched, so its structural features are
8
+ * degraded", "the WASM runtime aborted; restart to recover". Those must reach
9
+ * the human through the HOST's own render path, never a raw terminal write
10
+ * (pi owns the terminal — see the module doc in `extension-log.ts`).
11
+ *
12
+ * `index.ts` wires a getter at extension init; modules deep in the tree call
13
+ * `notifyUserDegradation` without knowing anything about `ctx`. Per the
14
+ * #338/#798 detached-callback rule the notifier is resolved through a GETTER
15
+ * at delivery time — never captured once, because a session replacement
16
+ * invalidates the previously captured `ctx.ui`.
17
+ *
18
+ * Fail-soft by construction: with no host wired (MCP server, CLI, tests) this
19
+ * is a no-op and the ndjson sink remains the sole destination — the message is
20
+ * never lost, only un-rendered.
21
+ */
22
+ let notifierGetter;
23
+ /** Called once from the extension entry with a getter over the live `ctx.ui.notify`. */
24
+ export function wireUserNotifier(portsOrGetter) {
25
+ notifierGetter =
26
+ typeof portsOrGetter === "function"
27
+ ? portsOrGetter
28
+ : () => portsOrGetter.notify.user;
29
+ }
30
+ /** Test/teardown-only: drop the wired host. */
31
+ export function resetUserNotifier() {
32
+ notifierGetter = undefined;
33
+ }
34
+ /** True when a host render path is available (for callers that want to branch). */
35
+ export function hasUserNotifier() {
36
+ return notifierGetter !== undefined;
37
+ }
38
+ /**
39
+ * Best-effort delivery of a user-facing degradation. Never throws — a stale
40
+ * `ctx` after a session replacement must degrade to a no-op, not break the
41
+ * diagnostic path that called it.
42
+ */
43
+ export function notifyUserDegradation(message, level = "warning") {
44
+ try {
45
+ const notify = notifierGetter?.();
46
+ notify?.(message, level);
47
+ }
48
+ catch {
49
+ // The ndjson sink already holds this message; a dead host is not an error.
50
+ }
51
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Vanished-instance markers (#1123 item 2, first slice — instance health).
3
+ *
4
+ * `deregisterInstance()` (clients/instance-registry.ts) SYNCHRONOUSLY removes
5
+ * a process's own entry from `instances.json` on a clean `session_shutdown`.
6
+ * That means the entry's mere PRESENCE in the registry, combined with a
7
+ * pid-confirmed-dead owner, is already proof the process never reached that
8
+ * shutdown path — no separate "clean shutdown" flag is needed on
9
+ * `InstanceEntry` (the registry already carries `heartbeatAt`/`rssBytes`,
10
+ * which is exactly the "lastSeen"/"rss" pair this marker needs; both are
11
+ * used AS-IS, per the instruction to add fields only if missing).
12
+ *
13
+ * `sweepOrphans()` (clients/instance-reaper.ts) already prunes these exact
14
+ * dead-pid entries out of the registry as part of #472's orphan-LSP reap —
15
+ * so this marker's read MUST happen against a snapshot taken before (or
16
+ * independently of) that prune, or the vanished set will already be empty by
17
+ * the time this runs. `logVanishedInstances` therefore takes the registry
18
+ * snapshot as an argument rather than reading it itself, so the caller
19
+ * controls ordering (see index.ts's session_start wiring, which reads once
20
+ * and passes the same snapshot to both this marker and `sweepOrphans`).
21
+ */
22
+ import { logSessionStart } from "./sessionstart-logger.js";
23
+ import { realIsPidAlive } from "./instance-reaper.js";
24
+ /**
25
+ * PURE: registry entries whose owning pid is confirmed dead. Every such entry
26
+ * is, by construction (see module docstring), one that exited without
27
+ * reaching `deregisterInstance()`. Uses the SAME conservative liveness
28
+ * contract as the reaper (`isPidAlive`, defaulting to `realIsPidAlive`):
29
+ * ESRCH-only-means-dead, any ambiguous signal (EPERM, unknown) stays "alive"
30
+ * — never flag a live-but-unverifiable instance as vanished.
31
+ */
32
+ export function detectVanishedInstances(registry, isPidAlive) {
33
+ return registry
34
+ .filter((entry) => !isPidAlive(entry.pid))
35
+ .map((entry) => ({
36
+ pid: entry.pid,
37
+ lastSeenAt: entry.heartbeatAt,
38
+ rssBytes: entry.rssBytes ?? 0,
39
+ }));
40
+ }
41
+ /**
42
+ * Log one `sessionstart.log` line per vanished instance found in `registry`.
43
+ * Best-effort (never throws into `session_start`) and read-only — this
44
+ * function never mutates or prunes the registry; that stays the reaper's job.
45
+ */
46
+ export function logVanishedInstances(registry, isPidAlive = realIsPidAlive) {
47
+ try {
48
+ const vanished = detectVanishedInstances(registry, isPidAlive);
49
+ for (const instance of vanished) {
50
+ const rssMb = Math.round(instance.rssBytes / (1024 * 1024));
51
+ logSessionStart(`previous instance pid ${instance.pid} last seen ${instance.lastSeenAt} (RSS ${rssMb}MB) exited without shutdown`);
52
+ }
53
+ }
54
+ catch {
55
+ // best-effort observability — never fail session_start over this
56
+ }
57
+ }
@@ -4,8 +4,8 @@ import * as path from "node:path";
4
4
  import { readInstanceRegistry, } from "./instance-registry.js";
5
5
  import { realIsPidAlive, STALE_HEARTBEAT_MS, } from "./instance-reaper.js";
6
6
  import { logLatency } from "./latency-logger.js";
7
- import { getLSPService } from "./lsp/index.js";
8
- import { contentHash, diagnosticsIpcPathForCwd, requestWarmCodeActions, requestWarmDiagnostics, WARM_CODE_ACTION_LOOKUP_LIMIT, WARM_DIAGNOSTICS_SCHEMA_VERSION, } from "./mcp/ipc.js";
7
+ import { loadLspService } from "./lsp-lazy.js";
8
+ import { contentHash, createWarmIpcLineReader, diagnosticsIpcPathForCwd, requestWarmCodeActions, requestWarmDiagnostics, WARM_CODE_ACTION_LOOKUP_LIMIT, WARM_DIAGNOSTICS_SCHEMA_VERSION, } from "./mcp/ipc.js";
9
9
  import { normalizeFilePath } from "./path-utils.js";
10
10
  const state = { local: true, servedDiagnosticHashes: new Map() };
11
11
  function record(event, cwd, reason, pid, source) {
@@ -41,7 +41,7 @@ async function serveRequest(req) {
41
41
  if (Date.now() > req.deadlineAt) {
42
42
  throw new Error("deadline exceeded");
43
43
  }
44
- return getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
44
+ return (await loadLspService()).getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
45
45
  }));
46
46
  const servedAt = Date.now();
47
47
  if (servedAt > req.deadlineAt)
@@ -67,7 +67,7 @@ async function serveRequest(req) {
67
67
  if (Date.now() > req.deadlineAt || contentHash(req.content) !== req.contentHash) {
68
68
  return { error: "stale request" };
69
69
  }
70
- const touched = await getLSPService().touchFile(req.file, req.content, {
70
+ const touched = await (await loadLspService()).getLSPService().touchFile(req.file, req.content, {
71
71
  diagnostics: "document",
72
72
  collectDiagnostics: true,
73
73
  clientScope: "with-auxiliary",
@@ -83,11 +83,23 @@ async function serveRequest(req) {
83
83
  result: {
84
84
  route: "diagnostics",
85
85
  version: WARM_DIAGNOSTICS_SCHEMA_VERSION,
86
- diagnostics: touched ?? [],
86
+ // #1179: `touchFile` now returns the `{ diags, inconclusive, binding }`
87
+ // wrapper — take the array off `.diags`. This is the canonical shape-5
88
+ // serialization boundary: the diagnostics array crosses the IPC socket
89
+ // and `inconclusive` is re-surfaced below as an EXPLICIT enumerable DTO
90
+ // field (no side-channel survives `JSON.stringify`).
91
+ diagnostics: touched?.diags ?? [],
87
92
  contentHash: req.contentHash,
88
93
  servedAt,
89
94
  fresh: servedAt <= req.deadlineAt && touched !== undefined,
90
95
  inconclusive: touched?.inconclusive === true,
96
+ // #1253: carry the touch's own confirmation verdict across the socket
97
+ // as an explicit enumerable field (same doctrine as `inconclusive`) —
98
+ // without it, an incumbent-served empty result from a silent-on-clean
99
+ // server is indistinguishable from "never answered" on the far side.
100
+ ...(touched?.confirmation === "confirmed"
101
+ ? { confirmation: "confirmed" }
102
+ : {}),
91
103
  },
92
104
  };
93
105
  }
@@ -104,22 +116,22 @@ function startServer(cwd) {
104
116
  }
105
117
  const server = net.createServer((socket) => {
106
118
  socket.setEncoding("utf8");
107
- let buffer = "";
108
- socket.on("data", (chunk) => {
109
- buffer += chunk;
110
- const newline = buffer.indexOf("\n");
111
- if (newline === -1)
112
- return;
119
+ // One-shot per connection (#1219 family): the same defect shape as the
120
+ // MCP warm socket clients write exactly one request and read one
121
+ // reply, so a handler that kept re-reading the same buffered line
122
+ // re-dispatched the request on stray bytes. The shared reader consumes
123
+ // the line and ignores anything after it.
124
+ socket.on("data", createWarmIpcLineReader((line) => {
113
125
  void (async () => {
114
126
  try {
115
- const req = JSON.parse(buffer.slice(0, newline));
127
+ const req = JSON.parse(line);
116
128
  socket.end(`${JSON.stringify(await serveRequest(req))}\n`);
117
129
  }
118
130
  catch (error) {
119
131
  socket.end(`${JSON.stringify({ error: String(error) })}\n`);
120
132
  }
121
133
  })();
122
- });
134
+ }));
123
135
  });
124
136
  server.on("error", (error) => {
125
137
  record("listener-error", cwd, String(error));
@@ -202,3 +214,11 @@ export function _setWarmAttachForTests(cwd, incumbentPid) {
202
214
  state.incumbentPid = incumbentPid;
203
215
  state.local = false;
204
216
  }
217
+ /**
218
+ * The incumbent-side request handler, exposed for tests. The socket wiring
219
+ * around it (`startServer`) can only be exercised by a test that actually
220
+ * binds a unix socket, which is not available in every sandbox — this seam
221
+ * lets the DTO-composition half (notably the #1253 `confirmation` field, whose
222
+ * absence is what a consumer reads as unconfirmed) be pinned directly.
223
+ */
224
+ export const _serveWarmRequestForTests = serveRequest;