@herbertgao/pi-extensions 2026.8.4 → 2026.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  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 +53 -14
  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 +18 -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 +20 -4
  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/fleet-list.ts +15 -6
  25. package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
  26. package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
  27. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
  28. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
  29. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
  30. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
  31. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
  32. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  33. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
  36. package/node_modules/@narumitw/pi-btw/README.md +32 -24
  37. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  38. package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
  39. package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
  40. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  41. package/node_modules/pi-lens/CHANGELOG.md +2535 -954
  42. package/node_modules/pi-lens/README.md +13 -0
  43. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
  44. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
  45. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
  46. package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
  47. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
  48. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
  49. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
  50. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
  51. package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
  52. package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
  53. package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
  54. package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
  55. package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
  56. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
  57. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  58. package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
  59. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
  60. package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
  61. package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
  62. package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
  63. package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
  64. package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
  65. package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
  66. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
  67. package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
  68. package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
  69. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
  70. package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
  71. package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
  72. package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
  73. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
  74. package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
  75. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
  76. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
  77. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
  78. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
  79. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
  80. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
  81. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
  82. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
  83. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
  84. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
  86. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
  87. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
  114. package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
  115. package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
  116. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  117. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
  118. package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
  119. package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
  120. package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
  121. package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
  122. package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
  123. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  124. package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
  125. package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
  126. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
  127. package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
  128. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
  129. package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
  130. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
  131. package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
  134. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
  135. package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
  136. package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
  137. package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
  138. package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
  139. package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
  140. package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
  141. package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
  142. package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
  143. package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
  144. package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
  145. package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
  146. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  147. package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
  148. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
  149. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
  150. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  151. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
  152. package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
  153. package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
  154. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
  155. package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
  156. package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
  157. package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
  158. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  159. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
  160. package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
  161. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
  162. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  163. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
  164. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
  165. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
  166. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
  167. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
  168. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
  169. package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
  170. package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
  171. package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
  172. package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
  173. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  174. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
  175. package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
  176. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
  177. package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
  178. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
  179. package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
  180. package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
  181. package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
  182. package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
  183. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
  184. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
  185. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
  186. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  187. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
  188. package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
  189. package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
  190. package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
  191. package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
  192. package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
  193. package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
  194. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
  195. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
  196. package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
  197. package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
  198. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
  199. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
  200. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
  201. package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
  202. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
  203. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
  204. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
  205. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
  206. package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
  207. package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
  208. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
  217. package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
  218. package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
  219. package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
  220. package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
  221. package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
  222. package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
  223. package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
  224. package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
  225. package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
  226. package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
  227. package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
  228. package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
  229. package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
  230. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
  233. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
  234. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
  235. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
  237. package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
  238. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
  239. package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
  240. package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
  241. package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
  242. package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
  243. package/node_modules/pi-lens/dist/index.js +51785 -36118
  244. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
  245. package/node_modules/pi-lens/dist/mcp/server.js +219 -46
  246. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  247. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  248. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
  249. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  250. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
  251. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
  252. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
  253. package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
  254. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  255. package/node_modules/pi-lens/docs/agent-guide.md +40 -15
  256. package/node_modules/pi-lens/docs/agent-tools.md +21 -10
  257. package/node_modules/pi-lens/docs/analysisall.md +192 -0
  258. package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
  259. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
  260. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
  261. package/node_modules/pi-lens/docs/environment-variables.md +44 -0
  262. package/node_modules/pi-lens/docs/fable.md +27 -0
  263. package/node_modules/pi-lens/docs/features.md +45 -3
  264. package/node_modules/pi-lens/docs/globalconfig.md +56 -1
  265. package/node_modules/pi-lens/docs/language-coverage.md +4 -3
  266. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
  267. package/node_modules/pi-lens/docs/mcp.md +37 -4
  268. package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
  269. package/node_modules/pi-lens/docs/settings.md +18 -1
  270. package/node_modules/pi-lens/docs/tools.md +4 -1
  271. package/node_modules/pi-lens/docs/usage.md +41 -5
  272. package/node_modules/pi-lens/docs/word-index.md +35 -0
  273. package/node_modules/pi-lens/package.json +10 -10
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
  300. package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
  301. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
  302. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
  303. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
  304. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  305. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
  306. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
  307. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  308. package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
  309. package/node_modules/pi-mcp-adapter/README.md +38 -4
  310. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  311. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
  312. package/node_modules/pi-mcp-adapter/cli.js +25 -4
  313. package/node_modules/pi-mcp-adapter/commands.ts +15 -7
  314. package/node_modules/pi-mcp-adapter/config.ts +4 -4
  315. package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
  316. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
  317. package/node_modules/pi-mcp-adapter/index.ts +8 -3
  318. package/node_modules/pi-mcp-adapter/init.ts +29 -5
  319. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
  320. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
  321. package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
  322. package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
  323. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
  324. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  325. package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
  326. package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
  327. package/node_modules/pi-mcp-adapter/package.json +4 -3
  328. package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
  329. package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
  330. package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
  331. package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
  332. package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
  333. package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
  334. package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
  335. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
  336. package/node_modules/pi-mcp-adapter/types.ts +176 -27
  337. package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
  338. package/node_modules/pi-web-access/CHANGELOG.md +14 -0
  339. package/node_modules/pi-web-access/README.md +18 -12
  340. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  341. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  342. package/node_modules/pi-web-access/curator-page.ts +5 -3
  343. package/node_modules/pi-web-access/curator-server.ts +2 -1
  344. package/node_modules/pi-web-access/extract.ts +106 -34
  345. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  346. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  347. package/node_modules/pi-web-access/gemini-search.ts +18 -4
  348. package/node_modules/pi-web-access/index.ts +120 -48
  349. package/node_modules/pi-web-access/package.json +2 -2
  350. package/node_modules/pi-web-access/summary-review.ts +11 -5
  351. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  352. package/package.json +12 -13
  353. package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
  354. package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
  355. package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
  356. package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
  357. package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
  358. package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
  359. package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
  360. 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,9 @@ 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 { touchCoverageGap } from "./lsp/diagnostic-binding.js";
8
+ import { loadLspService } from "./lsp-lazy.js";
9
+ import { contentHash, createWarmIpcLineReader, diagnosticsIpcPathForCwd, requestWarmCodeActions, requestWarmDiagnostics, WARM_CODE_ACTION_LOOKUP_LIMIT, WARM_DIAGNOSTICS_SCHEMA_VERSION, } from "./mcp/ipc.js";
9
10
  import { normalizeFilePath } from "./path-utils.js";
10
11
  const state = { local: true, servedDiagnosticHashes: new Map() };
11
12
  function record(event, cwd, reason, pid, source) {
@@ -41,7 +42,7 @@ async function serveRequest(req) {
41
42
  if (Date.now() > req.deadlineAt) {
42
43
  throw new Error("deadline exceeded");
43
44
  }
44
- return getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
45
+ return (await loadLspService()).getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
45
46
  }));
46
47
  const servedAt = Date.now();
47
48
  if (servedAt > req.deadlineAt)
@@ -67,7 +68,7 @@ async function serveRequest(req) {
67
68
  if (Date.now() > req.deadlineAt || contentHash(req.content) !== req.contentHash) {
68
69
  return { error: "stale request" };
69
70
  }
70
- const touched = await getLSPService().touchFile(req.file, req.content, {
71
+ const touched = await (await loadLspService()).getLSPService().touchFile(req.file, req.content, {
71
72
  diagnostics: "document",
72
73
  collectDiagnostics: true,
73
74
  clientScope: "with-auxiliary",
@@ -76,6 +77,11 @@ async function serveRequest(req) {
76
77
  source: "warm-attach-incumbent",
77
78
  });
78
79
  const servedAt = Date.now();
80
+ // #1470: the coverage gap is read through the shared helper, never re-derived
81
+ // from `confirmation === "partial"`. The two fields are set together today, so
82
+ // either test passes — which is exactly the coincidence `touchCoverageGap`'s
83
+ // own doc comment warns against. One reader, one rule.
84
+ const coverageGap = touchCoverageGap(touched);
79
85
  if (servedAt <= req.deadlineAt && touched !== undefined && !touched.inconclusive) {
80
86
  state.servedDiagnosticHashes.set(normalizeFilePath(req.file), req.contentHash);
81
87
  }
@@ -83,11 +89,34 @@ async function serveRequest(req) {
83
89
  result: {
84
90
  route: "diagnostics",
85
91
  version: WARM_DIAGNOSTICS_SCHEMA_VERSION,
86
- diagnostics: touched ?? [],
92
+ // #1179: `touchFile` now returns the `{ diags, inconclusive, binding }`
93
+ // wrapper — take the array off `.diags`. This is the canonical shape-5
94
+ // serialization boundary: the diagnostics array crosses the IPC socket
95
+ // and `inconclusive` is re-surfaced below as an EXPLICIT enumerable DTO
96
+ // field (no side-channel survives `JSON.stringify`).
97
+ diagnostics: touched?.diags ?? [],
87
98
  contentHash: req.contentHash,
88
99
  servedAt,
89
100
  fresh: servedAt <= req.deadlineAt && touched !== undefined,
90
101
  inconclusive: touched?.inconclusive === true,
102
+ // #1253: carry the touch's own confirmation verdict across the socket
103
+ // as an explicit enumerable field (same doctrine as `inconclusive`) —
104
+ // without it, an incumbent-served empty result from a silent-on-clean
105
+ // server is indistinguishable from "never answered" on the far side.
106
+ ...(touched?.confirmation === "confirmed"
107
+ ? { confirmation: "confirmed" }
108
+ : {}),
109
+ // #1470: a PARTIAL touch crosses the socket as itself rather than as a
110
+ // missing key. Omitting it would still fail closed on the far side, but it
111
+ // would be indistinguishable from an old incumbent that never sent the
112
+ // field — and the whole point of narrowing is that the reader can tell
113
+ // which coverage is real.
114
+ ...(coverageGap.length > 0
115
+ ? {
116
+ confirmation: "partial",
117
+ unconfirmedServerIds: [...coverageGap],
118
+ }
119
+ : {}),
91
120
  },
92
121
  };
93
122
  }
@@ -104,22 +133,22 @@ function startServer(cwd) {
104
133
  }
105
134
  const server = net.createServer((socket) => {
106
135
  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;
136
+ // One-shot per connection (#1219 family): the same defect shape as the
137
+ // MCP warm socket clients write exactly one request and read one
138
+ // reply, so a handler that kept re-reading the same buffered line
139
+ // re-dispatched the request on stray bytes. The shared reader consumes
140
+ // the line and ignores anything after it.
141
+ socket.on("data", createWarmIpcLineReader((line) => {
113
142
  void (async () => {
114
143
  try {
115
- const req = JSON.parse(buffer.slice(0, newline));
144
+ const req = JSON.parse(line);
116
145
  socket.end(`${JSON.stringify(await serveRequest(req))}\n`);
117
146
  }
118
147
  catch (error) {
119
148
  socket.end(`${JSON.stringify({ error: String(error) })}\n`);
120
149
  }
121
150
  })();
122
- });
151
+ }));
123
152
  });
124
153
  server.on("error", (error) => {
125
154
  record("listener-error", cwd, String(error));
@@ -202,3 +231,11 @@ export function _setWarmAttachForTests(cwd, incumbentPid) {
202
231
  state.incumbentPid = incumbentPid;
203
232
  state.local = false;
204
233
  }
234
+ /**
235
+ * The incumbent-side request handler, exposed for tests. The socket wiring
236
+ * around it (`startServer`) can only be exercised by a test that actually
237
+ * binds a unix socket, which is not available in every sandbox — this seam
238
+ * lets the DTO-composition half (notably the #1253 `confirmation` field, whose
239
+ * absence is what a consumer reads as unconfirmed) be pinned directly.
240
+ */
241
+ export const _serveWarmRequestForTests = serveRequest;