@herbertgao/pi-extensions 2026.8.11 → 2026.8.13

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 (476) hide show
  1. package/README.md +23 -10
  2. package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
  3. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
  4. package/node_modules/@czottmann/pi-automode/README.md +5 -3
  5. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
  6. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
  7. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
  8. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
  9. package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
  10. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
  11. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
  12. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
  15. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
  16. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
  17. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
  18. package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
  19. package/node_modules/@czottmann/pi-automode/package.json +4 -1
  20. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
  21. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  30. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
  31. package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
  32. package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
  35. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
  36. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
  38. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
  39. package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
  40. package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
  41. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
  42. package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
  43. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
  44. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  46. package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
  47. package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
  48. package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
  49. package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
  50. package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
  51. package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
  52. package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
  53. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
  54. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
  55. package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
  56. package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
  57. package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
  58. package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
  59. package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
  60. package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
  61. package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
  62. package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
  63. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
  64. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
  65. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
  66. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
  67. package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
  68. package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
  69. package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
  70. package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
  71. package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
  72. package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
  73. package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
  74. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
  75. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
  76. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
  77. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
  78. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
  79. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
  80. package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
  81. package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
  82. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
  83. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
  84. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
  85. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
  86. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
  87. package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
  88. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
  89. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
  90. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
  91. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
  92. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
  93. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
  94. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
  95. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
  96. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
  97. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
  98. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
  99. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
  100. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
  101. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
  102. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
  103. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
  104. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
  105. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
  106. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
  107. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
  108. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
  109. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
  110. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
  111. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
  112. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
  113. package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
  114. package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
  115. package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
  116. package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
  117. package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
  118. package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
  119. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
  120. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
  121. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
  122. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
  123. package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
  124. package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
  125. package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
  126. package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
  127. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
  128. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
  129. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
  130. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
  131. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
  132. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
  133. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
  134. package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
  135. package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
  136. package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
  137. package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
  138. package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
  139. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
  140. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
  141. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
  142. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
  143. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
  144. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
  145. package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
  146. package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
  147. package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
  148. package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
  149. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  150. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  151. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
  152. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
  153. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
  154. package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
  155. package/node_modules/@tifan/pi-handoff/package.json +43 -0
  156. package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
  157. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
  158. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
  159. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
  160. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
  161. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
  162. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
  163. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
  164. package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
  165. package/node_modules/@tifan/pi-recap/package.json +42 -0
  166. package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
  167. package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
  168. package/node_modules/@tifan/pi-rename/package.json +47 -0
  169. package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
  170. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
  171. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
  172. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
  173. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
  174. package/node_modules/pi-lens/CHANGELOG.md +96 -1
  175. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
  176. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
  177. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
  178. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
  179. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
  180. package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
  181. package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
  182. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
  183. package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
  184. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
  185. package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
  186. package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
  187. package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
  188. package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
  189. package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
  190. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
  191. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
  192. package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
  193. package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
  194. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
  195. package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
  196. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
  197. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
  198. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
  199. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
  200. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
  201. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
  202. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
  204. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
  205. package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
  206. package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
  207. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
  208. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
  209. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
  210. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
  211. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
  212. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
  213. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
  214. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
  215. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
  216. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
  217. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
  218. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
  219. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
  220. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
  221. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
  222. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
  223. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
  224. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
  225. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
  226. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
  227. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
  228. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
  229. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
  230. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
  231. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
  233. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
  234. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
  235. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
  236. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
  237. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
  238. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
  239. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
  240. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
  241. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
  242. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
  243. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
  244. package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
  245. package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
  246. package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
  247. package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
  248. package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
  249. package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
  250. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
  251. package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
  252. package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
  253. package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
  254. package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
  255. package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
  256. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
  257. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
  258. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
  259. package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
  260. package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
  261. package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
  262. package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
  263. package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
  264. package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
  265. package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
  266. package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
  267. package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
  268. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
  269. package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
  270. package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
  271. package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
  272. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
  273. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
  274. package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
  275. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
  276. package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
  277. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
  278. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
  279. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
  280. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
  281. package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
  282. package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
  283. package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
  284. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
  285. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
  286. package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
  287. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
  288. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
  289. package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
  290. package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
  291. package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
  292. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
  293. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
  294. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
  295. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
  296. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
  297. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
  298. package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
  299. package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
  300. package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
  301. package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
  302. package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
  303. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
  304. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
  305. package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
  306. package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
  307. package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
  308. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
  309. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
  310. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
  311. package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
  312. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
  313. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
  314. package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
  315. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
  316. package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
  317. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
  318. package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
  319. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
  320. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
  321. package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
  322. package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
  323. package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
  324. package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
  325. package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
  326. package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
  327. package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
  328. package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
  329. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
  330. package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
  331. package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
  332. package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
  333. package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
  334. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
  335. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  336. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
  337. package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
  338. package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
  339. package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
  340. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
  341. package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
  342. package/node_modules/pi-lens/dist/i18n.js +13 -5
  343. package/node_modules/pi-lens/dist/index.js +10797 -8627
  344. package/node_modules/pi-lens/dist/mcp/server.js +3 -1
  345. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
  346. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
  347. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
  348. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
  349. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
  350. package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
  351. package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
  352. package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
  353. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
  354. package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
  355. package/node_modules/pi-lens/package.json +160 -156
  356. package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
  357. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
  358. package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
  359. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
  360. package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
  361. package/node_modules/pi-mcp-adapter/README.md +42 -13
  362. package/node_modules/pi-mcp-adapter/commands.ts +4 -2
  363. package/node_modules/pi-mcp-adapter/config.ts +45 -5
  364. package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
  365. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
  366. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
  367. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
  368. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
  369. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
  370. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
  371. package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
  372. package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
  373. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
  374. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
  375. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
  376. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
  377. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
  378. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
  379. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
  380. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
  381. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
  382. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
  383. package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
  384. package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
  385. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
  386. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
  387. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
  388. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
  389. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
  390. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
  391. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
  392. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
  393. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
  394. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
  395. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
  396. package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
  397. package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
  398. package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
  399. package/node_modules/pi-mcp-adapter/index.ts +204 -82
  400. package/node_modules/pi-mcp-adapter/init.ts +41 -30
  401. package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
  402. package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
  403. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
  404. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
  405. package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
  406. package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
  407. package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
  408. package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
  409. package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
  410. package/node_modules/pi-mcp-adapter/package.json +24 -6
  411. package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
  412. package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
  413. package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
  414. package/node_modules/pi-mcp-adapter/state.ts +1 -3
  415. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
  416. package/node_modules/pi-mcp-adapter/types.ts +48 -1
  417. package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
  418. package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
  419. package/node_modules/pi-mcp-adapter/utils.ts +21 -19
  420. package/node_modules/pi-web-access/CHANGELOG.md +26 -0
  421. package/node_modules/pi-web-access/README.md +71 -14
  422. package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
  423. package/node_modules/pi-web-access/credential-source.ts +6 -2
  424. package/node_modules/pi-web-access/curator-page.ts +5 -3
  425. package/node_modules/pi-web-access/curator-server.ts +2 -1
  426. package/node_modules/pi-web-access/extract.ts +89 -9
  427. package/node_modules/pi-web-access/fetch-params.ts +13 -0
  428. package/node_modules/pi-web-access/gemini-adc.ts +298 -0
  429. package/node_modules/pi-web-access/gemini-api.ts +59 -15
  430. package/node_modules/pi-web-access/gemini-search.ts +58 -18
  431. package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
  432. package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
  433. package/node_modules/pi-web-access/gemini-web.ts +9 -3
  434. package/node_modules/pi-web-access/github-api.ts +5 -4
  435. package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
  436. package/node_modules/pi-web-access/index.ts +403 -297
  437. package/node_modules/pi-web-access/kimi-search.ts +234 -0
  438. package/node_modules/pi-web-access/openai-search.ts +118 -21
  439. package/node_modules/pi-web-access/package.json +3 -2
  440. package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
  441. package/node_modules/pi-web-access/utils.ts +307 -1
  442. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  443. package/package.json +46 -37
  444. package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
  445. package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
  446. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
  447. package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
  448. package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
  449. package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
  450. package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
  451. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
  452. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
  453. package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
  454. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
  455. package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
  456. package/node_modules/@herbertgao/pi-recap/package.json +0 -55
  457. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
  458. package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
  459. package/node_modules/@herbertgao/pi-rename/package.json +0 -63
  460. package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
  461. package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
  462. /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
  463. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
  464. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
  465. /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
  466. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
  467. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
  468. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
  469. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
  470. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
  471. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
  472. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
  473. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
  474. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
  475. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
  476. /package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/src/index.ts +0 -0
@@ -177,7 +177,15 @@ function gated(file, description, gates, evidence, extra = {}) {
177
177
  }
178
178
  /** Factory for a `labeled` entry — see {@link gated}'s doc for why this exists. */
179
179
  function labeled(file, description, reason, ageSource, evidence = [], extra = {}) {
180
- return { mode: "labeled", file, description, reason, ageSource, evidence, ...extra };
180
+ return {
181
+ mode: "labeled",
182
+ file,
183
+ description,
184
+ reason,
185
+ ageSource,
186
+ evidence,
187
+ ...extra,
188
+ };
181
189
  }
182
190
  const RUNTIME_TURN_FILE = "clients/runtime-turn.ts";
183
191
  const LENS_DIAGNOSTICS_FILE = "tools/lens-diagnostics.ts";
@@ -223,6 +231,15 @@ export const DELIVERY_SURFACES = {
223
231
  "runtime-turn:disposition-suppressed-notice": labeled(RUNTIME_TURN_FILE, "Turn-end running disposition-suppressed-count notice (#1616).", "A live running total accumulated from this turn's own gate/disposition " +
224
232
  "calls above (`dispositionSuppressedTotal`) — telemetry ABOUT the other " +
225
233
  "gated surfaces, not a cache of its own.", "live"),
234
+ // #2001/#2002 collect-later: findings an auxiliary LSP published AFTER its
235
+ // aux-grace window expired, probed from the client cache at the next
236
+ // turn_end. Gated on the mark timestamp: a cited file deleted or edited
237
+ // since the mark drops its findings (never delivered before, and the
238
+ // drifting edit already re-touched the file — a fresh pending pair
239
+ // supersedes this one), with both drop arms counted in the
240
+ // `late_auxiliary_findings` latency record rather than silenced.
241
+ "runtime-turn:late-auxiliary-findings": gated(RUNTIME_TURN_FILE, "Turn-end late-auxiliary LSP findings (collect-later probe of aux " +
242
+ "client caches whose grace window expired).", ["gateFindingsByPathFreshness"], ['store: "late-auxiliary-findings"']),
226
243
  "runtime-turn:cascade-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end 🧪 cascade neighbor blocker.", "Cascade results settle synchronously this turn where possible " +
227
244
  "(`settleCascadeRuns`), but an unsettled compute can carry over to a " +
228
245
  "later turn (bounded by a carry cap) — this round does not freshness-" +
@@ -246,7 +263,15 @@ export const DELIVERY_SURFACES = {
246
263
  partialReason: "call-graph freshness/invalidation policy is out of this PR's scope — " +
247
264
  "tracked as a follow-up, not silently assumed fresh.",
248
265
  }),
249
- "lens-diagnostics:mode-full": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=full` report.", ["applyDispositions", "applyRulePolicy", "reconcileProjectDiagnosticsSnapshot"], ["applyDispositions(", "applyRulePolicy(", "reconcileProjectDiagnosticsSnapshot("]),
266
+ "lens-diagnostics:mode-full": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=full` report.", [
267
+ "applyDispositions",
268
+ "applyRulePolicy",
269
+ "reconcileProjectDiagnosticsSnapshot",
270
+ ], [
271
+ "applyDispositions(",
272
+ "applyRulePolicy(",
273
+ "reconcileProjectDiagnosticsSnapshot(",
274
+ ]),
250
275
  "lens-diagnostics:mode-all": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=all` report (widget-state read).", ["reconcileStaleWidgetFiles", "reconcileStaleWidgetDependencyBlockers"], ["reconcileStaleWidgetFiles(", "reconcileStaleWidgetDependencyBlockers("]),
251
276
  // #1634 review round F3: this was the most important gap — the tool's
252
277
  // DEFAULT mode rendered cached `file:line` findings with zero freshness
@@ -269,6 +294,36 @@ export const DELIVERY_SURFACES = {
269
294
  "accumulator is drained and cleared at the moment of injection, so the " +
270
295
  "content IS the current state by construction.", "live"),
271
296
  "project-diagnostics:persisted-snapshot": gated(LENS_DIAGNOSTICS_FILE, "Cross-session persisted project-diagnostics snapshot read.", ["reconcileProjectDiagnosticsSnapshot"], ["reconcileProjectDiagnosticsSnapshot("]),
297
+ // ── #2028: the remaining agent-facing surfaces ──────────────────────────
298
+ // Registered after #2028's root-cause review found the 🔴 STOP block
299
+ // rendering stale/deleted-file blockers because its surface was never in
300
+ // this registry — the exact "gated or labeled, never neither" gap this
301
+ // module exists to close.
302
+ "tool-call:stop-blocker": gated("clients/pipeline.ts", "Per-edit 🔴 STOP blocker output appended to the write/edit tool result.", ["dropFindingsForMissingPaths"], ['store: "stop-blocker"']),
303
+ // The freshness stack itself (own-file mtime + reverse-dependency mtimes
304
+ // via isEntryFresh, plus the #1095 content binding) lives inside
305
+ // clients/lsp/workspace-diagnostics-cache.ts; the two evidence calls are
306
+ // the tool's literal entry points into that gated path.
307
+ "lsp-diagnostics:tool-output": gated("tools/lsp-diagnostics.ts", "`lsp_diagnostics` batch/directory sweep results. Cache hits replay through " +
308
+ "the shared workspace-diagnostics cache: createWorkspaceDiagnosticsCacheContext " +
309
+ "is the tool's entry, and its lookup() applies the #671/#672 freshness stack " +
310
+ "(own-file mtime + reverse-dependency mtimes via isEntryFresh) plus the " +
311
+ "#1095 content binding.", [
312
+ "createWorkspaceDiagnosticsCacheContext",
313
+ "isEntryFresh",
314
+ "cacheCtx.lookup",
315
+ ], [
316
+ "createWorkspaceDiagnosticsCacheContext(resolvedCwd)",
317
+ "cacheCtx.lookup(file, scopeKey)",
318
+ ]),
319
+ "git-guard:commit-blocked": labeled("clients/git-guard.ts", "Git-guard commit/push 🔴 COMMIT BLOCKED verdict (--lens-guard).", "Synchronous preflight rejection returned inline with the failed git " +
320
+ "command — no stored state is delivered, so nothing can go stale between " +
321
+ "detection and delivery.", "live"),
322
+ "read-guard-tool-lines:preflight-errors": labeled("clients/read-guard-tool-lines.ts", "Read-guard hashline BLOCKED / RE-READ REQUIRED preflight errors.", "Computed fresh per edit attempt and returned as that attempt's rejection — " +
323
+ "no cached findings are replayed, so there is no staleness window.", "live"),
324
+ "tool-call:duplicate-export-blocker": labeled("clients/runtime-tool-call.ts", "Duplicate-export STOP rejection returned inline with the failed edit.", "Synchronous preflight rejection computed per edit attempt; no stored state.", "live"),
325
+ "agent-behavior:thrashing-notice": labeled("clients/agent-behavior-client.ts", "In-result thrashing/blind-write detection notice.", "Ephemeral notice computed at detection time inside the same tool result — " +
326
+ "no persistence and no cache, so nothing can be stale.", "live"),
272
327
  };
273
328
  function assertPartialStatusHasReason(id, entry) {
274
329
  if (entry.status === "partial" && !entry.partialReason) {
@@ -491,7 +491,7 @@ const EXPLICIT_FORMATTER_CONFIG_CHECKS = new Map([
491
491
  ["mix", (cwd) => hasMixFormatConfig(cwd)],
492
492
  ]);
493
493
  function hasExplicitFormatterConfig(formatterName, cwd, ext) {
494
- return EXPLICIT_FORMATTER_CONFIG_CHECKS.get(formatterName)?.(cwd, ext) ?? false;
494
+ return (EXPLICIT_FORMATTER_CONFIG_CHECKS.get(formatterName)?.(cwd, ext) ?? false);
495
495
  }
496
496
  // Exported for the "every registered formatter is selectable" coverage guard
497
497
  // (formatter-policy-consistency.test.ts, #1572): derived from the table above,
@@ -509,7 +509,8 @@ async function hasEditorConfig(cwd) {
509
509
  }
510
510
  }
511
511
  async function indentationArgs(filePath, tool, cwd) {
512
- if (await hasEditorConfig(cwd) || hasExplicitFormatterConfig(tool, cwd, path.extname(filePath))) {
512
+ if ((await hasEditorConfig(cwd)) ||
513
+ hasExplicitFormatterConfig(tool, cwd, path.extname(filePath))) {
513
514
  return [];
514
515
  }
515
516
  let content;
@@ -524,9 +525,15 @@ async function indentationArgs(filePath, tool, cwd) {
524
525
  return null;
525
526
  const indentation = detectIndentation(content);
526
527
  if (tool === "shfmt")
527
- return indentation.style === "tab" ? ["-i", "0"] : ["-i", String(indentation.width)];
528
+ return indentation.style === "tab"
529
+ ? ["-i", "0"]
530
+ : ["-i", String(indentation.width)];
528
531
  if (tool === "prettier") {
529
- return [indentation.style === "tab" ? "--use-tabs" : "--no-use-tabs", "--tab-width", String(indentation.width)];
532
+ return [
533
+ indentation.style === "tab" ? "--use-tabs" : "--no-use-tabs",
534
+ "--tab-width",
535
+ String(indentation.width),
536
+ ];
530
537
  }
531
538
  if (tool === "ruff") {
532
539
  // `ruff format` has NO --indent-style/--indent-width flags (it errors with
@@ -540,7 +547,12 @@ async function indentationArgs(filePath, tool, cwd) {
540
547
  `format.indent-style='${indentation.style}'`,
541
548
  ];
542
549
  }
543
- return ["--indent-style", indentation.style, "--indent-width", String(indentation.width)];
550
+ return [
551
+ "--indent-style",
552
+ indentation.style,
553
+ "--indent-width",
554
+ String(indentation.width),
555
+ ];
544
556
  }
545
557
  /**
546
558
  * Every biome invocation must carry this. Biome exits 1 with "No files were
@@ -671,9 +683,35 @@ export const prettierFormatter = {
671
683
  hasNearestPackageJsonField(cwd, "prettier"));
672
684
  },
673
685
  };
686
+ /**
687
+ * Turns "no target files left after ignore rules" into a clean exit 0.
688
+ *
689
+ * oxfmt is offered for every extension in `OXFMT_SUPPORTED_EXTENSIONS` as soon
690
+ * as a config exists, but a config's `ignorePatterns` can exclude any of them.
691
+ * Handed a path it has been told to ignore, oxfmt 0.64.0 exits 2 with
692
+ * "Expected at least one target file. All matched files may have been excluded
693
+ * by ignore rules." Under the #1337 strict default that reads as a formatting
694
+ * failure, so a user whose oxfmt config ignores (say) Markdown sees an error on
695
+ * every Markdown edit.
696
+ *
697
+ * Same class as biome's "No files were processed in the specified paths", and
698
+ * the same fix: ask the tool not to treat an empty target set as an error,
699
+ * rather than teaching `formatFile` to forgive an exit code. This is the
700
+ * narrower repair — a flag cannot mask anything else, whereas status- or
701
+ * message-keyed leniency would have to be trusted to stay tight across oxfmt
702
+ * releases. Verified against oxfmt 0.64.0: with the flag, an ignored path exits
703
+ * 0 untouched, a normal file is still rewritten, and an unparseable file still
704
+ * exits 2. `tests/clients/dispatch/oxfmt-ignored-file-noop.test.ts` pins all
705
+ * three against the real binary.
706
+ *
707
+ * The flag also silences a genuinely missing file, which `formatFile` never
708
+ * reaches: it reads the file before it spawns anything, so a missing path
709
+ * fails there.
710
+ */
711
+ const OXFMT_NO_ERROR_ON_UNMATCHED = "--no-error-on-unmatched-pattern";
674
712
  export const oxfmtFormatter = {
675
713
  name: "oxfmt",
676
- command: ["oxfmt", "$FILE"],
714
+ command: ["oxfmt", OXFMT_NO_ERROR_ON_UNMATCHED, "$FILE"],
677
715
  // #1337 audit: oxfmt (and the `vp fmt --write` path) publish no exit-code
678
716
  // table. `--write` is the default and `--check` is the separate verification
679
717
  // mode, so there is no documented nonzero-on-reformat. Absent a documented
@@ -681,6 +719,9 @@ export const oxfmtFormatter = {
681
719
  // mode of guessing wrong the other way is a silent no-op (#1336).
682
720
  async resolveCommand(filePath, cwd) {
683
721
  if (hasVitePlusConfig(cwd)) {
722
+ // No unmatched-pattern flag here: this is `vp`, a different CLI with
723
+ // its own arguments. Whether `vp fmt` has the same empty-target
724
+ // behavior is unverified, so nothing is claimed about it.
684
725
  const localVp = await findInNodeModules("vp", cwd);
685
726
  if (localVp)
686
727
  return [localVp, "fmt", filePath, "--write"];
@@ -690,10 +731,10 @@ export const oxfmtFormatter = {
690
731
  }
691
732
  const local = await findInNodeModules("oxfmt", cwd);
692
733
  if (local)
693
- return [local, filePath];
734
+ return [local, OXFMT_NO_ERROR_ON_UNMATCHED, filePath];
694
735
  const found = await which("oxfmt");
695
736
  if (found)
696
- return [found, filePath];
737
+ return [found, OXFMT_NO_ERROR_ON_UNMATCHED, filePath];
697
738
  return null;
698
739
  },
699
740
  // Single source of truth: OXFMT_SUPPORTED_EXTENSIONS in tool-policy.ts.
@@ -834,7 +875,10 @@ export const shfmtFormatter = {
834
875
  const inPath = await which("shfmt");
835
876
  if (inPath)
836
877
  return [inPath, "-w", ...styleArgs, filePath];
837
- return resolveManagedSmartDefaultCommand("shfmt", filePath, ["-w", ...styleArgs]);
878
+ return resolveManagedSmartDefaultCommand("shfmt", filePath, [
879
+ "-w",
880
+ ...styleArgs,
881
+ ]);
838
882
  },
839
883
  async detect(_cwd) {
840
884
  if ((await which("shfmt")) !== null)
@@ -1290,28 +1334,88 @@ const detectionCache = new BoundedLruCache(32);
1290
1334
  // Kotlin/Spotless gradle files, sqlfluff's setup.cfg, and oxfmt's
1291
1335
  // vite-plus.json / additional vite.config extensions).
1292
1336
  const FORMATTER_CONFIG_FILES = [
1293
- "package.json", "biome.json", "biome.jsonc", ".prettierrc", ".prettierrc.json",
1294
- ".prettierrc.yml", ".prettierrc.yaml", ".prettierrc.js", ".prettierrc.cjs",
1295
- ".prettierrc.mjs", "prettier.config.js", "prettier.config.cjs", "prettier.config.mjs",
1296
- "prettier.config.ts", "pyproject.toml", "ruff.toml", ".ruff.toml", "black.toml",
1297
- ".black", "tox.ini", "setup.cfg", "requirements.txt", "Pipfile", ".sqlfluff", ".rubocop.yml", ".rubocop.yaml", "Gemfile", ".clang-format",
1298
- "_clang-format", ".php-cs-fixer.php", ".php-cs-fixer.dist.php", "stylua.toml",
1299
- ".stylua.toml", ".ocamlformat", ".editorconfig", ".google-java-format",
1300
- ".ktfmt", ".ktfmt.kts", "build.gradle.kts", "build.gradle", "settings.gradle.kts", "settings.gradle",
1301
- ".cljfmt.edn", "cljfmt.edn", ".cljfmt",
1302
- ".cmake-format", ".cmake-format.yaml", ".cmake-format.yml", ".cmake-format.json", ".cmake-format.py",
1303
- "cmake-format.py", "cmake-format.yaml", "cmake-format.yml",
1304
- "oxfmt.toml", ".oxfmtrc.json", "vite-plus.json",
1305
- "vite.config.ts", "vite.config.mts", "vite.config.cts", "vite.config.js", "vite.config.mjs", "vite.config.cjs",
1306
- "PSScriptAnalyzerSettings.psd1", "ScriptAnalyzerSettings.psd1",
1337
+ "package.json",
1338
+ "biome.json",
1339
+ "biome.jsonc",
1340
+ ".prettierrc",
1341
+ ".prettierrc.json",
1342
+ ".prettierrc.yml",
1343
+ ".prettierrc.yaml",
1344
+ ".prettierrc.js",
1345
+ ".prettierrc.cjs",
1346
+ ".prettierrc.mjs",
1347
+ "prettier.config.js",
1348
+ "prettier.config.cjs",
1349
+ "prettier.config.mjs",
1350
+ "prettier.config.ts",
1351
+ "pyproject.toml",
1352
+ "ruff.toml",
1353
+ ".ruff.toml",
1354
+ "black.toml",
1355
+ ".black",
1356
+ "tox.ini",
1357
+ "setup.cfg",
1358
+ "requirements.txt",
1359
+ "Pipfile",
1360
+ ".sqlfluff",
1361
+ ".rubocop.yml",
1362
+ ".rubocop.yaml",
1363
+ "Gemfile",
1364
+ ".clang-format",
1365
+ "_clang-format",
1366
+ ".php-cs-fixer.php",
1367
+ ".php-cs-fixer.dist.php",
1368
+ "stylua.toml",
1369
+ ".stylua.toml",
1370
+ ".ocamlformat",
1371
+ ".editorconfig",
1372
+ ".google-java-format",
1373
+ ".ktfmt",
1374
+ ".ktfmt.kts",
1375
+ "build.gradle.kts",
1376
+ "build.gradle",
1377
+ "settings.gradle.kts",
1378
+ "settings.gradle",
1379
+ ".cljfmt.edn",
1380
+ "cljfmt.edn",
1381
+ ".cljfmt",
1382
+ ".cmake-format",
1383
+ ".cmake-format.yaml",
1384
+ ".cmake-format.yml",
1385
+ ".cmake-format.json",
1386
+ ".cmake-format.py",
1387
+ "cmake-format.py",
1388
+ "cmake-format.yaml",
1389
+ "cmake-format.yml",
1390
+ "oxfmt.toml",
1391
+ ".oxfmtrc.json",
1392
+ "vite-plus.json",
1393
+ "vite.config.ts",
1394
+ "vite.config.mts",
1395
+ "vite.config.cts",
1396
+ "vite.config.js",
1397
+ "vite.config.mjs",
1398
+ "vite.config.cjs",
1399
+ "PSScriptAnalyzerSettings.psd1",
1400
+ "ScriptAnalyzerSettings.psd1",
1307
1401
  // #1595 sweep additions.
1308
- ".csharpierrc", ".csharpierrc.json", ".csharpierrc.yaml", ".csharpierrc.yml",
1309
- ".ormolu", "taplo.toml", ".taplo.toml", ".terraform.lock.hcl", ".swiftformat",
1310
- ".fantomasignore", ".formatter.exs",
1402
+ ".csharpierrc",
1403
+ ".csharpierrc.json",
1404
+ ".csharpierrc.yaml",
1405
+ ".csharpierrc.yml",
1406
+ ".ormolu",
1407
+ "taplo.toml",
1408
+ ".taplo.toml",
1409
+ ".terraform.lock.hcl",
1410
+ ".swiftformat",
1411
+ ".fantomasignore",
1412
+ ".formatter.exs",
1311
1413
  ];
1312
1414
  async function formatterConfigSignature(cwd) {
1313
1415
  const paths = await findUp(FORMATTER_CONFIG_FILES, cwd);
1314
- const parts = await Promise.all(paths.sort((a, b) => a.localeCompare(b)).map(async (filePath) => {
1416
+ const parts = await Promise.all(paths
1417
+ .sort((a, b) => a.localeCompare(b))
1418
+ .map(async (filePath) => {
1315
1419
  try {
1316
1420
  const stat = await fs.stat(filePath);
1317
1421
  return `${filePath}:${stat.mtimeMs}:${stat.size}`;
@@ -1529,6 +1633,19 @@ export function clearFormatterCache() {
1529
1633
  detectionCache.clear();
1530
1634
  resetWhichLatches();
1531
1635
  }
1636
+ /**
1637
+ * Test-only internals access for the session-state registry probe (#1895):
1638
+ * the conformance suite must arm all four pieces of state this reset claims
1639
+ * to cover and prove none survives.
1640
+ */
1641
+ export function _getFormatterResetStateForTests() {
1642
+ return {
1643
+ whichLatchByCommand,
1644
+ whichTransientCommands,
1645
+ cooldownRecordedForRetryAtMs,
1646
+ detectionCache,
1647
+ };
1648
+ }
1532
1649
  export function clearFormatterRuntimeState() {
1533
1650
  detectionCache.clear();
1534
1651
  resetWhichLatches();
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Freshness kernel (#1739): ONE comparator and ONE verdict type for every
3
+ * "was this file modified after my reference timestamp?" gate.
4
+ *
5
+ * The same staleness comparison was independently reimplemented in at least
6
+ * six stores (advisory-provenance, blocker-freshness,
7
+ * project-diagnostics/cache [#1711], widget-state ×3, lsp/workspace-
8
+ * diagnostics-cache), and three of those copies carried the identical
9
+ * mtime-tolerance defect fixed separately in #1710/#1711/#1664. This module
10
+ * is the single implementation going forward; the registered-or-fail sweep
11
+ * (`tests/clients/freshness-sweep.test.ts`) fails on new out-of-kernel
12
+ * comparisons so the population cannot silently regrow.
13
+ *
14
+ * Deliberately NOT here: age-based checks (`Date.now() - mtime > TTL` — that
15
+ * is expiry, not freshness against a reference event) and max-selection
16
+ * comparisons (`mtime > best.mtimeMs`) — neither compares against a scan or
17
+ * record timestamp, which is what this kernel's verdict means.
18
+ */
19
+ /** Shared drift tolerance: raised from 0 to 50ms after measured Windows mtime skew produced 42 false demotions in 50 runs (#1710 evidence). */
20
+ export const MTIME_DRIFT_TOLERANCE_MS = 50;
21
+ /**
22
+ * Compare an observed mtime against a reference timestamp (the scan, record,
23
+ * or touch instant whose validity depends on the file not having moved).
24
+ *
25
+ * `mtimeMs === undefined` means the caller had no readable mtime (stat
26
+ * failed, file gone). The kernel does NOT choose a policy for that case -
27
+ * callers differ legitimately (a diagnostics cache drops, a drift detector
28
+ * skips) - so it reports `indeterminate` and the caller maps it.
29
+ */
30
+ export function freshnessFromMtime(input) {
31
+ const tolerance = input.toleranceMs ?? MTIME_DRIFT_TOLERANCE_MS;
32
+ if (input.mtimeMs === undefined) {
33
+ return { verdict: "indeterminate", reason: "no-mtime-evidence" };
34
+ }
35
+ return input.mtimeMs > input.referenceMs + tolerance
36
+ ? { verdict: "stale", reason: "modified-after-reference" }
37
+ : { verdict: "fresh" };
38
+ }
@@ -152,7 +152,8 @@ function canonicalizeGuardCommand(command) {
152
152
  if (!quote && (ch === "'" || ch === '"')) {
153
153
  quote = ch === "'" ? "single" : "double";
154
154
  }
155
- else if ((quote === "single" && ch === "'") || (quote === "double" && ch === '"')) {
155
+ else if ((quote === "single" && ch === "'") ||
156
+ (quote === "double" && ch === '"')) {
156
157
  quote = undefined;
157
158
  }
158
159
  }
@@ -241,7 +242,10 @@ function containsGuardedSubstitution(command, depth) {
241
242
  : command.startsWith(">(", i)
242
243
  ? delimitedSubstitutionBody(command, i, ">(", ")")
243
244
  : ch === "`"
244
- ? { body: command.slice(i + 1, command.indexOf("`", i + 1)), end: command.indexOf("`", i + 1) }
245
+ ? {
246
+ body: command.slice(i + 1, command.indexOf("`", i + 1)),
247
+ end: command.indexOf("`", i + 1),
248
+ }
245
249
  : undefined;
246
250
  if (substitution && substitution.end >= 0) {
247
251
  const nested = canonicalizeGuardCommand(substitution.body);
@@ -309,7 +313,13 @@ function containsCommitOrPush(tokens, depth) {
309
313
  i += 1;
310
314
  continue;
311
315
  }
312
- if (["--config-env", "--git-dir", "--work-tree", "--exec-path", "--namespace"].some((prefix) => option.startsWith(`${prefix}=`))) {
316
+ if ([
317
+ "--config-env",
318
+ "--git-dir",
319
+ "--work-tree",
320
+ "--exec-path",
321
+ "--namespace",
322
+ ].some((prefix) => option.startsWith(`${prefix}=`))) {
313
323
  i += 1;
314
324
  continue;
315
325
  }
@@ -319,12 +329,15 @@ function containsCommitOrPush(tokens, depth) {
319
329
  return verbs.length === 1 && (verbs[0] === "commit" || verbs[0] === "push");
320
330
  }
321
331
  const leadingExecutable = commandTokens[0] ?? "";
322
- const knownCommandStringWrapper = isShellWrapper(leadingExecutable) || isCommandStringWrapper(leadingExecutable);
332
+ const knownCommandStringWrapper = isShellWrapper(leadingExecutable) ||
333
+ isCommandStringWrapper(leadingExecutable);
323
334
  if (!knownCommandStringWrapper) {
324
335
  // Unknown launchers are a fail-closed boundary only when they explicitly
325
336
  // accept a command string. Re-tokenizing the value keeps literal mentions
326
337
  // such as `myprog -c "echo git push"` out of the guarded-command path.
327
- const unknownSwitchIndex = commandTokens.slice(1).findIndex((token) => (token.startsWith("-") || token.startsWith("/")) && token.length > 1);
338
+ const unknownSwitchIndex = commandTokens
339
+ .slice(1)
340
+ .findIndex((token) => (token.startsWith("-") || token.startsWith("/")) && token.length > 1);
328
341
  if (unknownSwitchIndex < 0)
329
342
  return false;
330
343
  const commandIndex = unknownSwitchIndex + 2;
@@ -389,7 +402,8 @@ function isTurnEndFindingsCache(value) {
389
402
  !!record.fileContentHashes &&
390
403
  typeof record.fileContentHashes === "object" &&
391
404
  Object.values(record.fileContentHashes).every((hash) => typeof hash === "string") &&
392
- (record.affectedFilesTruncated === undefined || typeof record.affectedFilesTruncated === "boolean") &&
405
+ (record.affectedFilesTruncated === undefined ||
406
+ typeof record.affectedFilesTruncated === "boolean") &&
393
407
  (record.blockingFiles === undefined || Array.isArray(record.blockingFiles)));
394
408
  }
395
409
  function cacheRecord(cacheManager, cwd) {
@@ -413,7 +427,10 @@ export function writeGitGuardRecord(cacheManager, runtime, cwd, record) {
413
427
  cwd,
414
428
  runtime,
415
429
  generation: 0,
416
- files: capped.files.map((file) => ({ path: file, role: "affected" })),
430
+ files: capped.files.map((file) => ({
431
+ path: file,
432
+ role: "affected",
433
+ })),
417
434
  truncated: capped.truncated,
418
435
  });
419
436
  const fileContentHashes = Object.fromEntries(currentProvenance.files.map((file) => [
@@ -523,7 +540,9 @@ export function syncGitGuardRecord(runtime, cacheManager, cwd, editedFilePath) {
523
540
  markCacheUnknown(runtime, "blocking_provenance_untrusted");
524
541
  return;
525
542
  }
526
- const editedKey = editedFilePath ? guardPathKey(editedFilePath, cwd) : undefined;
543
+ const editedKey = editedFilePath
544
+ ? guardPathKey(editedFilePath, cwd)
545
+ : undefined;
527
546
  const testFiles = existing?.testFailureFiles ?? [];
528
547
  const remainingBlockingFiles = editedKey && existingBlockingFiles.length > 0
529
548
  ? existingBlockingFiles.filter((file) => guardPathKey(file, cwd) !== editedKey)
@@ -553,7 +572,10 @@ export function syncGitGuardRecord(runtime, cacheManager, cwd, editedFilePath) {
553
572
  : existing?.blockerContent;
554
573
  const hasTestFailures = existing?.testFailures === true;
555
574
  const hasBlockers = !!blockerContent || hasTestFailures;
556
- const content = [blockerContent, hasTestFailures ? existing?.testFailureContent : undefined]
575
+ const content = [
576
+ blockerContent,
577
+ hasTestFailures ? existing?.testFailureContent : undefined,
578
+ ]
557
579
  .filter((value) => !!value)
558
580
  .join("\n\n");
559
581
  if (!hasBlockers && !content) {
@@ -612,7 +634,9 @@ export function clearGitGuardTestFailure(cacheManager, cwd, runtime, passedFiles
612
634
  const existing = cacheRecord(cacheManager, cwd);
613
635
  if (!existing?.testFailures)
614
636
  return;
615
- const passedKeys = new Set((passedFiles.length > 0 ? passedFiles : existing.testFailureFiles ?? []).map((file) => guardPathKey(file, cwd)));
637
+ const passedKeys = new Set((passedFiles.length > 0
638
+ ? passedFiles
639
+ : (existing.testFailureFiles ?? [])).map((file) => guardPathKey(file, cwd)));
616
640
  const remainingFiles = (existing.testFailureFiles ?? []).filter((file) => !passedKeys.has(guardPathKey(file, cwd)));
617
641
  const blockerContent = existing.blockerContent ?? "";
618
642
  if (!blockerContent && remainingFiles.length === 0) {
@@ -634,7 +658,9 @@ export function clearGitGuardTestFailure(cacheManager, cwd, runtime, passedFiles
634
658
  sessionId: runtime.telemetrySessionId,
635
659
  projectSeqStart: runtime.turnStartProjectSeq,
636
660
  projectSeqEnd: runtime.projectSeq,
637
- fileSeqByPath: Object.fromEntries(runtime.getFileSeqEntries().map(([filePath, seq]) => [guardPathKey(filePath, cwd), seq])),
661
+ fileSeqByPath: Object.fromEntries(runtime
662
+ .getFileSeqEntries()
663
+ .map(([filePath, seq]) => [guardPathKey(filePath, cwd), seq])),
638
664
  fileContentHashes: {},
639
665
  });
640
666
  }
@@ -643,7 +669,9 @@ export function evaluateGitGuard(runtime, cacheManager, cwd) {
643
669
  logDecision(cwd, "blocked", "runtime_blockers", {
644
670
  projectSeq: runtime.projectSeq,
645
671
  });
646
- const detail = runtime.gitGuardSummary ? `\n${runtime.gitGuardSummary}` : "";
672
+ const detail = runtime.gitGuardSummary
673
+ ? `\n${runtime.gitGuardSummary}`
674
+ : "";
647
675
  return {
648
676
  block: true,
649
677
  reason: `🔴 COMMIT BLOCKED (--lens-guard): unresolved blockers must be fixed before commit/push.${detail}\nRun lens_diagnostics mode=all for full details, then commit again.`,
@@ -713,7 +741,9 @@ export function evaluateGitGuard(runtime, cacheManager, cwd) {
713
741
  }
714
742
  // A deleted/ignored affected file has been resolved; no stale blocker is
715
743
  // allowed to survive solely because its old path remains in the record.
716
- if (record.hasBlockers && liveFiles.length === 0 && record.affectedFiles.length > 0) {
744
+ if (record.hasBlockers &&
745
+ liveFiles.length === 0 &&
746
+ record.affectedFiles.length > 0) {
717
747
  logDecision(cwd, "allowed", "affected_files_resolved", {
718
748
  projectSeq: record.projectSeqEnd,
719
749
  });
@@ -33,9 +33,7 @@ export class GoClient {
33
33
  availability;
34
34
  log;
35
35
  constructor(verbose = false) {
36
- this.log = verbose
37
- ? createSubsystemLogger("go")
38
- : () => { };
36
+ this.log = verbose ? createSubsystemLogger("go") : () => { };
39
37
  this.availability = createToolchainAvailability({
40
38
  tool: "go",
41
39
  label: "Go",
@@ -33,7 +33,7 @@ export const GRAMMAR_SOURCE_OVERRIDES = {
33
33
  };
34
34
  /** The URL a grammar wasm is fetched from (override if any, else the aggregator). */
35
35
  export function grammarSourceUrl(filename) {
36
- return GRAMMAR_SOURCE_OVERRIDES[filename]?.url ?? `${GRAMMAR_CDN_BASE}/${filename}`;
36
+ return (GRAMMAR_SOURCE_OVERRIDES[filename]?.url ?? `${GRAMMAR_CDN_BASE}/${filename}`);
37
37
  }
38
38
  /**
39
39
  * Grammars built in-house and committed to `vendor/grammars/`.
@@ -38,7 +38,7 @@ import { stagePathFor } from "./atomic-write-staging.js";
38
38
  * the caller must treat as a persist failure (both persist workers fall back
39
39
  * to a main-thread rewrite on an error result).
40
40
  */
41
- export async function writeGzipStageFile(data, stagePath, testDelayMs) {
41
+ export async function writeGzipStageFile(data, stagePath, testDelayMs, options) {
42
42
  const tmpPath = stagePathFor(stagePath);
43
43
  try {
44
44
  if (testDelayMs) {
@@ -48,6 +48,18 @@ export async function writeGzipStageFile(data, stagePath, testDelayMs) {
48
48
  const json = JSON.stringify(data);
49
49
  const serializeMs = performance.now() - serializeStarted;
50
50
  const rawBytes = Buffer.byteLength(json);
51
+ const semanticFingerprint = options?.semanticFingerprint?.(json);
52
+ if (semanticFingerprint !== undefined &&
53
+ options?.skipIfFingerprints?.includes(semanticFingerprint)) {
54
+ return {
55
+ rawBytes,
56
+ gzBytes: 0,
57
+ serializeMs,
58
+ writeMs: 0,
59
+ semanticFingerprint,
60
+ skippedUnchanged: true,
61
+ };
62
+ }
51
63
  const writeStarted = performance.now();
52
64
  await fs.promises.mkdir(path.dirname(stagePath), { recursive: true });
53
65
  const chunks = function* () {
@@ -60,7 +72,13 @@ export async function writeGzipStageFile(data, stagePath, testDelayMs) {
60
72
  await fs.promises.rename(tmpPath, stagePath);
61
73
  const writeMs = performance.now() - writeStarted;
62
74
  const gzBytes = (await fs.promises.stat(stagePath)).size;
63
- return { rawBytes, gzBytes, serializeMs, writeMs };
75
+ return {
76
+ rawBytes,
77
+ gzBytes,
78
+ serializeMs,
79
+ writeMs,
80
+ semanticFingerprint,
81
+ };
64
82
  }
65
83
  catch (err) {
66
84
  await fs.promises.rm(tmpPath, { force: true }).catch(() => { });
@@ -76,7 +94,7 @@ export async function writeGzipStageFile(data, stagePath, testDelayMs) {
76
94
  * each supplies only how to derive its own result's routing fields from the
77
95
  * request. Throws immediately if loaded outside a worker thread.
78
96
  */
79
- export function serveGzipStageWorker(buildBaseResult) {
97
+ export function serveGzipStageWorker(buildBaseResult, options) {
80
98
  const port = parentPort;
81
99
  if (!port) {
82
100
  throw new Error("gzip stage persist worker requires a parent port");
@@ -87,11 +105,19 @@ export function serveGzipStageWorker(buildBaseResult) {
87
105
  ...buildBaseResult(request),
88
106
  };
89
107
  try {
90
- const metrics = await writeGzipStageFile(request.data, request.stagePath, request.testDelayMs);
108
+ const fingerprint = options?.semanticFingerprint;
109
+ const metrics = await writeGzipStageFile(request.data, request.stagePath, request.testDelayMs, {
110
+ semanticFingerprint: fingerprint
111
+ ? (json) => fingerprint(request, json)
112
+ : undefined,
113
+ skipIfFingerprints: options?.skipIfFingerprints?.(request),
114
+ });
91
115
  result.rawBytes = metrics.rawBytes;
92
116
  result.gzBytes = metrics.gzBytes;
93
117
  result.serializeMs = metrics.serializeMs;
94
118
  result.writeMs = metrics.writeMs;
119
+ result.semanticFingerprint = metrics.semanticFingerprint;
120
+ result.skippedUnchanged = metrics.skippedUnchanged;
95
121
  }
96
122
  catch (err) {
97
123
  result.error = err instanceof Error ? err.message : String(err);
@@ -128,9 +128,7 @@ export function hostWouldApplyOldText(content, oldText) {
128
128
  const fuzzyContent = normalizeForFuzzyMatch(c);
129
129
  const fuzzyOldText = normalizeForFuzzyMatch(o);
130
130
  const fuzzyFound = fuzzyContent.indexOf(fuzzyOldText) !== -1;
131
- const occurrences = fuzzyOldText.length === 0
132
- ? 0
133
- : fuzzyContent.split(fuzzyOldText).length - 1;
131
+ const occurrences = fuzzyOldText.length === 0 ? 0 : fuzzyContent.split(fuzzyOldText).length - 1;
134
132
  return {
135
133
  wouldApply: (exactFound || fuzzyFound) && occurrences === 1,
136
134
  occurrences,
@@ -52,7 +52,8 @@ export function collectInstallDiagnostics() {
52
52
  const pj = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
53
53
  return String(pj.version ?? "unknown");
54
54
  }, "unknown");
55
- const bunVersion = globalThis.Bun?.version;
55
+ const bunVersion = globalThis.Bun
56
+ ?.version;
56
57
  const runtime = bunVersion
57
58
  ? `bun ${bunVersion}`
58
59
  : `node ${process.versions.node}`;
@@ -88,7 +89,8 @@ export function collectInstallDiagnostics() {
88
89
  }, false);
89
90
  const grammars = safe(() => {
90
91
  let dir = path.dirname(require.resolve("web-tree-sitter"));
91
- while (path.basename(dir) !== "web-tree-sitter" && dir !== path.dirname(dir)) {
92
+ while (path.basename(dir) !== "web-tree-sitter" &&
93
+ dir !== path.dirname(dir)) {
92
94
  dir = path.dirname(dir);
93
95
  }
94
96
  return fs.existsSync(path.join(dir, "grammars", "tree-sitter-typescript.wasm"));