@herbertgao/pi-extensions 2026.8.6 → 2026.8.8

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 (385) hide show
  1. package/README.md +8 -6
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +320 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +79 -17
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +5 -4
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +5 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +140 -97
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  51. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
  52. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
  53. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
  54. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
  55. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
  56. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
  57. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
  58. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  59. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  60. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  61. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  62. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  63. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  64. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  65. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  66. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  67. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
  68. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  69. package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
  70. package/node_modules/pi-lens/CHANGELOG.md +999 -0
  71. package/node_modules/pi-lens/README.md +117 -3
  72. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  73. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  74. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  75. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  76. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  77. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  78. package/node_modules/pi-lens/dist/clients/bash-file-access.js +381 -13
  79. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  80. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  81. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +129 -0
  82. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  83. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  84. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +206 -0
  85. package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
  86. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  87. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  88. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  89. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  90. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  91. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  92. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  93. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  94. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +84 -14
  95. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
  96. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  97. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
  98. package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
  99. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  100. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  102. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  103. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  104. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -2
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +17 -8
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +188 -0
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +21 -10
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  144. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  145. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  146. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  147. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +316 -0
  148. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  149. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  150. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  151. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  152. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  153. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  154. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  155. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  156. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  157. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  158. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  159. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  160. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  161. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  162. package/node_modules/pi-lens/dist/clients/jscpd-client.js +87 -8
  163. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  164. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  165. package/node_modules/pi-lens/dist/clients/language-profile.js +9 -2
  166. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  167. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  168. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  169. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  170. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +128 -8
  171. package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
  172. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  173. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/index.js +2423 -151
  175. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  176. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  177. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  178. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  179. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  180. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  181. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  182. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  183. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  184. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  185. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  186. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  187. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  188. package/node_modules/pi-lens/dist/clients/module-report.js +22 -1
  189. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
  190. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  191. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  192. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  193. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  194. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  195. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  198. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  199. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  200. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  201. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +23 -9
  202. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  203. package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
  204. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  205. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  206. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  207. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +8 -3
  208. package/node_modules/pi-lens/dist/clients/read-guard.js +253 -10
  209. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  210. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  211. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
  212. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  213. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
  214. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
  215. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  216. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  217. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +352 -45
  218. package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -9
  219. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  220. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  221. package/node_modules/pi-lens/dist/clients/runtime-turn.js +620 -67
  222. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  223. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  224. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  225. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  226. package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
  227. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  228. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  229. package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
  230. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  231. package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  233. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  234. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  235. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  237. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  238. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
  239. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  240. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  241. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  242. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  243. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  244. package/node_modules/pi-lens/dist/index.js +61407 -48577
  245. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
  246. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  247. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  248. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  249. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  250. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  251. package/node_modules/pi-lens/docs/features.md +19 -5
  252. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  253. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  254. package/node_modules/pi-lens/docs/mcp.md +2 -2
  255. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  256. package/node_modules/pi-lens/docs/settings.md +19 -1
  257. package/node_modules/pi-lens/docs/usage.md +1 -0
  258. package/node_modules/pi-lens/package.json +27 -10
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  319. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  320. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  321. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  322. package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
  323. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
  324. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
  325. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
  326. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  327. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  328. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  329. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  330. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  331. package/node_modules/pi-mcp-adapter/README.md +47 -5
  332. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  333. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  334. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  335. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  336. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  337. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  338. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  339. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  340. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  341. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  342. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  343. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  344. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  345. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  346. package/node_modules/pi-mcp-adapter/package.json +3 -1
  347. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  348. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  349. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  350. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  351. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  352. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  353. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  354. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  355. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  356. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  357. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  358. package/node_modules/pi-web-access/README.md +32 -13
  359. package/node_modules/pi-web-access/anysearch.ts +4 -2
  360. package/node_modules/pi-web-access/brave.ts +16 -4
  361. package/node_modules/pi-web-access/chrome-cookies.ts +86 -15
  362. package/node_modules/pi-web-access/curator-page.ts +6 -3
  363. package/node_modules/pi-web-access/curator-server.ts +4 -1
  364. package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
  365. package/node_modules/pi-web-access/exa.ts +18 -7
  366. package/node_modules/pi-web-access/extract.ts +40 -5
  367. package/node_modules/pi-web-access/firecrawl.ts +18 -2
  368. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  369. package/node_modules/pi-web-access/github-extract.ts +65 -36
  370. package/node_modules/pi-web-access/index.ts +60 -61
  371. package/node_modules/pi-web-access/openai-search.ts +17 -6
  372. package/node_modules/pi-web-access/package.json +1 -1
  373. package/node_modules/pi-web-access/page-query.ts +4 -2
  374. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  375. package/node_modules/pi-web-access/parallel.ts +2 -2
  376. package/node_modules/pi-web-access/pdf-extract.ts +18 -5
  377. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  378. package/node_modules/pi-web-access/serper.ts +211 -0
  379. package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
  380. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  381. package/node_modules/pi-web-access/summary-review.ts +44 -22
  382. package/node_modules/pi-web-access/tavily.ts +16 -4
  383. package/node_modules/pi-web-access/utils.ts +87 -0
  384. package/node_modules/pi-web-access/valyu.ts +199 -0
  385. package/package.json +14 -14
@@ -1,18 +1,22 @@
1
1
  import * as nodeCrypto from "node:crypto";
2
2
  import * as nodeFs from "node:fs";
3
3
  import * as path from "node:path";
4
- import { extractReadPathsFromCommand, extractGrepSearchReadsFromOutput, extractWrittenPathsFromCommand, } from "./bash-file-access.js";
4
+ import { noteAuthoritativeContentAttachment } from "./agent-nudge.js";
5
+ import { extractReadPathsFromCommand, extractDeletedPathsFromCommand, extractGrepSearchReadsFromOutput, extractWrittenPathsFromCommand, } from "./bash-file-access.js";
5
6
  import { registerSearchReads, } from "./search-read-registration.js";
6
7
  import { createFileTime } from "./file-time.js";
7
8
  import { publishFormatQueued } from "./format-events-publish.js";
8
9
  import { isPathIgnoredByProject } from "./file-utils.js";
9
10
  import { getFormatService } from "./format-service.js";
10
- import { isExternalOrVendorFile, normalizeEphemeralMapKey } from "./path-utils.js";
11
+ import { isExternalOrVendorFile, normalizeEphemeralMapKey, pathsEqual } from "./path-utils.js";
11
12
  import { PathKeyedMap } from "./path-keyed-map.js";
12
13
  import { resolveLanguageRootForFile } from "./language-profile.js";
13
14
  import { logLatency } from "./latency-logger.js";
15
+ import { resolveToolCallCorrelationId } from "./tool-event.js";
14
16
  import { boundedIndexesForCount, createReadGuardEditBatchSummary, getReadGuardCorrelationId, logReadGuardEvent, } from "./read-guard-logger.js";
17
+ import { notifyExternalFileChange } from "./lsp/index.js";
15
18
  import { runPipeline } from "./pipeline.js";
19
+ import { renderPostAutofixNotice, } from "./post-autofix-notice.js";
16
20
  import { appendProjectChange, } from "./project-changes.js";
17
21
  import { syncGitGuardRecord } from "./git-guard.js";
18
22
  import { scheduleWordIndexPersist } from "./word-index.js";
@@ -203,14 +207,104 @@ export async function handleToolResult(deps) {
203
207
  const { event, getFlag, getFlagSource, dbg, runtime, cacheManager, biomeClient, ruffClient, metricsClient, resetLSPService, agentBehaviorRecord, formatBehaviorWarnings, } = deps;
204
208
  const rawFilePath = event.input.path;
205
209
  const workspaceRoot = runtime.projectRoot || process.cwd();
210
+ // #1642: a gitignored worktree edit got re-attributed onto a
211
+ // same-relative-path file in the parent checkout because this handler
212
+ // used to always resolve a relative path against `workspaceRoot`
213
+ // (`runtime.projectRoot`), with no idea the call actually ran under a
214
+ // different cwd/worktree.
215
+ //
216
+ // Source-level correction (pi host audit, earendil-works/pi): tool_call's
217
+ // own resolved path is NOT authoritative for what executed —
218
+ // `agent-session.ts:914-919`'s extension-handler contract lets a LATER
219
+ // `tool_call` handler mutate `event.input` in place with no
220
+ // re-validation, and edit's `prepareArguments` rewrites args before the
221
+ // event fires at all. `tool_result.input`, by contrast, is populated
222
+ // from the EXECUTED args (`agent-session.ts:502-516`) — it is the
223
+ // authoritative path source. So the correlation record's job is narrower
224
+ // than "the path": it is the RESOLUTION BASIS (the cwd/worktree the call
225
+ // actually ran under). Every tool_result resolves ITS OWN authoritative
226
+ // `rawFilePath` against that basis, rather than trusting a call-time path
227
+ // that a later handler may have superseded.
228
+ const toolCallId = resolveToolCallCorrelationId(event);
229
+ const attribution = toolCallId !== undefined
230
+ ? runtime.takeToolCallAttribution(toolCallId)
231
+ : undefined;
232
+ let resolutionBasis;
233
+ if (attribution) {
234
+ resolutionBasis = attribution.originCwd;
235
+ }
236
+ else if (toolCallId !== undefined && rawFilePath && !path.isAbsolute(rawFilePath)) {
237
+ // A real correlation id existed (the host DOES support one) but no
238
+ // attribution was recorded under it — evicted, cleared because the
239
+ // call was blocked before it could execute, or simply never seen by
240
+ // `handleToolCall`. A RELATIVE path here is ambiguous: we have no
241
+ // idea which cwd it is relative to, and guessing `workspaceRoot` is
242
+ // exactly the #1642 collapse. Fail CLOSED instead of guessing — no
243
+ // turn state, no deferred work — and log it so a real incident is
244
+ // countable rather than silently mis-attributed.
245
+ const guessedPath = path.resolve(workspaceRoot, rawFilePath);
246
+ // Existence is not execution evidence: a same-named file can exist in
247
+ // the workspace while the tool ran in another cwd. Without the recorded
248
+ // call target and origin cwd there is no comparison to make, so retain the
249
+ // full record and fail closed.
250
+ dbg(`path_attribution_missing: no recorded resolution basis for toolCallId=${toolCallId}, refusing relative path ${rawFilePath} (would have guessed ${guessedPath})`);
251
+ logLatency({
252
+ type: "phase",
253
+ toolName: event.toolName,
254
+ filePath: guessedPath,
255
+ phase: "path_attribution_missing",
256
+ durationMs: 0,
257
+ metadata: { toolCallId, rawFilePath, guessedPath },
258
+ });
259
+ return;
260
+ }
261
+ else {
262
+ // Either an ABSOLUTE path (bash-synthetic writes always pass one —
263
+ // unambiguous regardless of any basis, see the bash-write dispatch
264
+ // below) or a host that supplies NO correlation id at all under any
265
+ // known field name. The latter cannot be correlated by identity full
266
+ // stop; this is the SAME exposure every host had before this fix,
267
+ // not a regression introduced by it.
268
+ resolutionBasis = workspaceRoot;
269
+ }
206
270
  const filePath = rawFilePath
207
271
  ? path.isAbsolute(rawFilePath)
208
272
  ? rawFilePath
209
- : path.resolve(workspaceRoot, rawFilePath)
273
+ : path.resolve(resolutionBasis, rawFilePath)
210
274
  : rawFilePath;
275
+ // Purely diagnostic: tool_call's call-time verdict (computed on ITS OWN
276
+ // resolved path, which may since have been superseded) disagreed with
277
+ // what actually executed. This does NOT gate anything by itself — the
278
+ // ignore re-check below, running on the freshly & correctly resolved
279
+ // `filePath`, is the real decision — but a divergence is exactly the
280
+ // shape of the reported incident, so it is named legibly.
281
+ if (attribution?.skipped &&
282
+ filePath &&
283
+ attribution.resolvedPath &&
284
+ !pathsEqual(filePath, attribution.resolvedPath)) {
285
+ const message = `path_attribution_refused: call target ${attribution.resolvedPath} (originCwd=${attribution.originCwd}) vs tool_result resolved ${filePath}`;
286
+ dbg(message);
287
+ logLatency({
288
+ type: "phase",
289
+ toolName: event.toolName,
290
+ filePath,
291
+ phase: "path_attribution_refused",
292
+ durationMs: 0,
293
+ metadata: {
294
+ callTarget: attribution.resolvedPath,
295
+ resolvedPath: filePath,
296
+ originCwd: attribution.originCwd,
297
+ },
298
+ });
299
+ }
211
300
  const behaviorWarnings = agentBehaviorRecord(event.toolName, filePath);
212
301
  const syntheticWriteContent = [];
213
- let syntheticAttachmentBytes = 0;
302
+ // #1590: one shared authoritative-content budget for every path this bash
303
+ // command wrote. It is handed DOWN to each synthetic call so the single
304
+ // attachment decision there sees both limits; nothing re-decides out here.
305
+ const syntheticAttachmentBudget = {
306
+ remaining: AUTHORITATIVE_CONTENT_MAX_BYTES,
307
+ };
214
308
  // Bash writes (redirects, tee, sed -i, cp/mv, touch, git checkout/restore) —
215
309
  // these change file content but never go through the edit tool, so bash
216
310
  // early-returns before the dispatch pipeline below. For each in-project file
@@ -237,49 +331,14 @@ export async function handleToolResult(deps) {
237
331
  event: { ...event, toolName: "write", input: { path: wp } },
238
332
  _bypassDebounce: true,
239
333
  _autofixMode: autofixMode,
334
+ _attachmentBudget: syntheticAttachmentBudget,
240
335
  });
241
336
  if (syntheticResult) {
242
- // The per-attachment cap bounds each file, but a multi-file bash
243
- // write (`sed -i` over globs, `;`-chained rewrites) appends one
244
- // attachment per path — share ONE authoritative-content budget
245
- // across the whole command so the aggregate tool result stays
246
- // bounded too. Past the budget, degrade to the re-read warning.
247
- for (const block of syntheticResult.content.slice(event.content.length)) {
248
- const blockBytes = typeof block.text === "string"
249
- ? Buffer.byteLength(block.text, "utf-8")
250
- : 0;
251
- const isAuthoritativeAttachment = typeof block.text === "string" &&
252
- block.text.startsWith("pi-lens applied autofix to ");
253
- if (isAuthoritativeAttachment &&
254
- syntheticAttachmentBytes + blockBytes >
255
- AUTHORITATIVE_CONTENT_MAX_BYTES) {
256
- // S3e (#1432 review): this is the SECOND
257
- // `authoritative_content_attachment_decision` row for `wp` —
258
- // the synthetic `handleToolResult` call above already logged
259
- // an "attached" row for the same path under its per-file
260
- // cap. This outer, aggregate-budget row is logged later and
261
- // is the one that matches what the caller actually sees
262
- // (the re-read warning below, not the attachment), so it
263
- // wins for `wp`; the inner "attached" row is a stale
264
- // per-file view superseded by this shared-budget decision.
265
- logLatency({
266
- type: "phase",
267
- phase: "authoritative_content_attachment_decision",
268
- filePath: wp,
269
- durationMs: 0,
270
- metadata: { path: wp, bytes: blockBytes, decision: "aggregate-budget-degraded" },
271
- });
272
- syntheticWriteContent.push({
273
- type: "text",
274
- text: `⚠️ **File was modified by auto-format/fix. You MUST re-read ${wp} before making any further edits — the aggregate authoritative content for this command is too large to attach.**`,
275
- });
276
- continue;
277
- }
278
- if (isAuthoritativeAttachment) {
279
- syntheticAttachmentBytes += blockBytes;
280
- }
281
- syntheticWriteContent.push(block);
282
- }
337
+ // #1590: forward verbatim. The synthetic call already charged the
338
+ // shared budget above and phrased its own notice from the decision
339
+ // it made, so a second verdict out here could only contradict it —
340
+ // which is exactly the defect this shape produced before.
341
+ syntheticWriteContent.push(...syntheticResult.content.slice(event.content.length));
283
342
  }
284
343
  }
285
344
  if (event.isError !== true && !getFlag("no-read-guard")) {
@@ -301,6 +360,42 @@ export async function handleToolResult(deps) {
301
360
  });
302
361
  }
303
362
  }
363
+ // #1668: bash-deleted files never go through the edit tool, so nothing
364
+ // else tells an LSP server one of its watched files is gone — the ONLY
365
+ // existing enqueue site fires on first open and can only emit type 1/2.
366
+ // Extract the command's likely delete targets, confirm each by existence
367
+ // (never scan the workspace — only the paths the command named), and only
368
+ // act on paths pi-lens already knows about (a read or a write this
369
+ // session) so an `rm` on something pi-lens never touched is not treated
370
+ // as a signal. Each match is routed to already-active LSP clients as a
371
+ // type-3 watched-files event through the same #271 coalescing queue a
372
+ // burst of deletes still flushes as one notification per server.
373
+ if (event.isError !== true &&
374
+ !getFlag("no-lsp") &&
375
+ !getFlag("no-read-guard")) {
376
+ for (const dp of extractDeletedPathsFromCommand(command, workspaceRoot)) {
377
+ if (isExternalOrVendorFile(dp, workspaceRoot))
378
+ continue;
379
+ if (isPathIgnoredByProject(dp, workspaceRoot, false))
380
+ continue;
381
+ if (!deps.readGuard || !deps.readGuard.hasKnownPath(dp))
382
+ continue;
383
+ // #1668 review F4: this is the ONLY gate standing between a merely
384
+ // NAMED path and an actual confirmed delete — extractDeletedPathsFromCommand
385
+ // only proposes candidates from parsing the command text, so it can't
386
+ // tell `git rm --cached f` (index-only, file still on disk) from a
387
+ // real delete, can't see a short-circuited `rm f && false` that never
388
+ // ran, and can't resolve a relative path run from a `cd`-ed subdirectory
389
+ // against the wrong cwd. Every one of those is caught here, and only
390
+ // here — do not remove or reorder this check relative to the loop body.
391
+ if (nodeFs.existsSync(dp))
392
+ continue; // still there — not a real delete
393
+ deps.readGuard.forgetPath(dp);
394
+ void notifyExternalFileChange(dp, 3).catch((err) => {
395
+ dbg(`tool_result: external-delete notify failed for ${dp}: ${err}`);
396
+ });
397
+ }
398
+ }
304
399
  }
305
400
  // Search tools reveal specific lines (file:line) the agent then edits — register
306
401
  // those shown lines (± context) as reads so the follow-up edit isn't blocked (#169).
@@ -467,13 +562,15 @@ export async function handleToolResult(deps) {
467
562
  const dispatchCwd = resolveLanguageRootForFile(filePath, workspaceRoot);
468
563
  const turnStateCwd = path.resolve(workspaceRoot);
469
564
  dbg(`tool_result: resolved dispatch cwd ${dispatchCwd} for ${filePath} (turnState cwd ${turnStateCwd})`);
470
- if (event.model || event.provider || event.sessionId || event.session?.id) {
471
- runtime.setTelemetryIdentity({
472
- model: event.model,
473
- provider: event.provider,
474
- sessionId: event.sessionId ?? event.session?.id,
475
- });
476
- }
565
+ // #1655 item 2: a `setTelemetryIdentity` call used to sit here, gated on
566
+ // `event.model`/`provider`/`sessionId`/`session.id`. pi sets none of those on
567
+ // a `tool_result` — `afterToolCall` builds the event with exactly
568
+ // `type`/`toolName`/`toolCallId`/`input`/`content`/`details`/`isError`/`usage`
569
+ // (`@earendil-works/pi-coding-agent/dist/core/agent-session.js:243-256`,
570
+ // source `src/core/agent-session.ts:502-516`), so the gate was always false
571
+ // against a real host and the branch never ran. Identity for this dispatch
572
+ // comes from the runtime, which `message_start`/`session_start` populate —
573
+ // see the `telemetry:` block handed to `runPipeline` below.
477
574
  const writeIndex = runtime.nextWriteIndex();
478
575
  let modifiedRanges;
479
576
  try {
@@ -555,6 +652,9 @@ export async function handleToolResult(deps) {
555
652
  projectSeq: () => runtime.projectSeq,
556
653
  getFilesChangedSince: (seq) => runtime.getFilesChangedSince(seq),
557
654
  },
655
+ // The settle clock is live because the deferred cascade may reach its
656
+ // budget derivation before or after turn_end starts waiting.
657
+ turnEndCascadeSettleStart: () => runtime.getTurnEndCascadeSettleStart(),
558
658
  // #348 phase 2: live reference so the deferred cascade can update the
559
659
  // warm word index in place at the same seam as the graph rebuild.
560
660
  // `runtime.wordIndex` is read fresh (not captured) via this closure-free
@@ -709,7 +809,7 @@ export async function handleToolResult(deps) {
709
809
  let autofixNewlyQueued = false;
710
810
  if (!result.isError && autofixMode === "deferred" && nodeFs.existsSync(filePath)) {
711
811
  autofixNewlyQueued =
712
- runtime.deferMutation?.call(runtime, filePath, dispatchCwd, event.toolName, turnStateCwd, "autofix", deps.sessionId) ?? false;
812
+ runtime.deferMutation?.call(runtime, filePath, dispatchCwd, event.toolName, turnStateCwd, "autofix", deps.sessionId, resolutionBasis) ?? false;
713
813
  dbg(`tool_result: queued deferred autofix for ${filePath}`);
714
814
  }
715
815
  let formatQueued = false;
@@ -717,7 +817,7 @@ export async function handleToolResult(deps) {
717
817
  !getFlag("no-autoformat", filePath) &&
718
818
  (autofixMode === "deferred" || !getFlag("immediate-format")) &&
719
819
  nodeFs.existsSync(filePath)) {
720
- const isNewlyQueued = runtime.deferFormat(filePath, dispatchCwd, event.toolName, turnStateCwd, deps.sessionId);
820
+ const isNewlyQueued = runtime.deferFormat(filePath, dispatchCwd, event.toolName, turnStateCwd, deps.sessionId, resolutionBasis);
721
821
  formatQueued = true;
722
822
  dbg(`tool_result: queued deferred format for ${filePath}`);
723
823
  logLatency({
@@ -811,7 +911,10 @@ export async function handleToolResult(deps) {
811
911
  }
812
912
  }
813
913
  if (result.inlineBlockerSummary) {
814
- runtime.recordInlineBlockers(filePath, result.inlineBlockerSummary);
914
+ // #1561: stamp the verdict with THIS dispatch's write token — the same
915
+ // counter `lsp_diagnostics`' reconciliation seam draws from — so a later
916
+ // confirmed-clean result can be ordered against it instead of racing it.
917
+ runtime.recordInlineBlockers(filePath, result.inlineBlockerSummary, writeIndex, result.inlineBlockerSources, result.inlineBlockerLines);
815
918
  }
816
919
  else {
817
920
  runtime.clearInlineBlockers(filePath);
@@ -842,39 +945,69 @@ export async function handleToolResult(deps) {
842
945
  result: output ? "completed" : "no_output",
843
946
  });
844
947
  runtime.reportedThisTurn.add(filePath);
948
+ // --- The ONE authoritative-attachment decision (#1590) ---
949
+ // Everything downstream — the attached block, the telemetry row, the nudge
950
+ // suppression, and the notice sentence — reads this single verdict. It is
951
+ // the only place that sees both limits: the per-file cap and the shared
952
+ // per-command budget a multi-file bash write threads in.
845
953
  const postMutation = result.postMutation;
846
- const attachAuthoritativeContent = postMutation !== undefined &&
847
- Buffer.byteLength(postMutation.content, "utf-8") <= AUTHORITATIVE_CONTENT_MAX_BYTES;
848
- if (postMutation) {
849
- const bytes = Buffer.byteLength(postMutation.content, "utf-8");
850
- // S3e (#1432 review): when this call is the synthetic per-file
851
- // `handleToolResult` recursion a multi-file bash write drives (see the
852
- // bash branch above), the OUTER aggregate-budget loop may log a SECOND
853
- // `authoritative_content_attachment_decision` row for this same
854
- // `filePath` right after this one, downgrading an "attached" here to
855
- // "aggregate-budget-degraded" once the shared budget is exhausted.
856
- // Both rows are intentional (this one reflects the per-file cap
857
- // decision; the outer one reflects the aggregate-budget decision that
858
- // can override it) — the outer row, logged later, wins for that path.
954
+ const attachmentText = postMutation
955
+ ? `pi-lens applied autofix to ${postMutation.filePath}. The following full content is authoritative for subsequent edits:\n\n${postMutation.content}`
956
+ : "";
957
+ const contentBytes = postMutation
958
+ ? Buffer.byteLength(postMutation.content, "utf-8")
959
+ : 0;
960
+ const withinPerFileCap = contentBytes <= AUTHORITATIVE_CONTENT_MAX_BYTES;
961
+ const budget = deps._attachmentBudget;
962
+ const withinSharedBudget = !budget || Buffer.byteLength(attachmentText, "utf-8") <= budget.remaining;
963
+ const attachAuthoritativeContent = postMutation !== undefined && withinPerFileCap && withinSharedBudget;
964
+ const attachmentDecision = !postMutation
965
+ ? "none"
966
+ : attachAuthoritativeContent
967
+ ? "attached"
968
+ : withinPerFileCap
969
+ ? "aggregate-budget-degraded"
970
+ : "size-capped";
971
+ // #1590: the pipeline hands up the changed-file data and this layer renders
972
+ // the sentence, so a size-capped write can no longer carry both "attached
973
+ // content is authoritative" and "too large to attach". The fallback covers
974
+ // a post-mutation with no notice data, which must still say re-read.
975
+ const notice = result.postAutofixNotice ??
976
+ (postMutation
977
+ ? { targetPath: postMutation.filePath, changedFiles: [] }
978
+ : undefined);
979
+ if (postMutation && attachAuthoritativeContent && budget) {
980
+ budget.remaining -= Buffer.byteLength(attachmentText, "utf-8");
981
+ }
982
+ // #1590 review F1: every mutation that produced a notice logs a row,
983
+ // INCLUDING the `none` decision a format-only change makes. Gating the row
984
+ // on `postMutation` made a legitimate "nothing was attachable here" verdict
985
+ // indistinguishable from missing instrumentation, which is the same
986
+ // empty-vs-errored confusion the read paths already guard against.
987
+ if (postMutation || notice) {
859
988
  logLatency({
860
989
  type: "phase",
861
990
  phase: "authoritative_content_attachment_decision",
862
- filePath: postMutation.filePath,
991
+ filePath: postMutation?.filePath ?? filePath,
863
992
  durationMs: 0,
864
- metadata: { path: postMutation.filePath, bytes, decision: attachAuthoritativeContent ? "attached" : "size-capped" },
993
+ metadata: {
994
+ path: postMutation?.filePath ?? filePath,
995
+ bytes: contentBytes,
996
+ decision: attachmentDecision,
997
+ },
865
998
  });
866
999
  }
1000
+ if (postMutation) {
1001
+ // #1464: the nudge suppresses exactly the paths this decision
1002
+ // delivered. Same boolean the attachment below reads — the nudge layer
1003
+ // never re-derives the cap or the budget for itself.
1004
+ noteAuthoritativeContentAttachment(postMutation.filePath, attachAuthoritativeContent);
1005
+ }
867
1006
  const returnedContent = attachAuthoritativeContent
868
- ? [
869
- ...event.content,
870
- {
871
- type: "text",
872
- text: `pi-lens applied autofix to ${postMutation.filePath}. The following full content is authoritative for subsequent edits:\n\n${postMutation.content}`,
873
- },
874
- ]
1007
+ ? [...event.content, { type: "text", text: attachmentText }]
875
1008
  : event.content;
876
- if (postMutation && !attachAuthoritativeContent) {
877
- output = `${output ? `${output}\n\n` : ""}⚠️ **File was modified by auto-format/fix. You MUST re-read ${postMutation.filePath} before making any further edits — the authoritative content is too large to attach.**`;
1009
+ if (notice) {
1010
+ output = `${output ? `${output}\n\n` : ""}${renderPostAutofixNotice(notice, attachmentDecision)}`;
878
1011
  }
879
1012
  if (!output && !result.postMutation)
880
1013
  return;