@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
@@ -55,8 +55,7 @@ export function parseMadgeSkips(stderr) {
55
55
  const headerIdx = lines.findIndex((l) => /Skipped\s+\d+\s+file/i.test(l));
56
56
  if (headerIdx === -1)
57
57
  return { total: 0, local: [] };
58
- const total = Number.parseInt(lines[headerIdx].match(/Skipped\s+(\d+)/i)?.[1] ?? "0", 10) ||
59
- 0;
58
+ const total = Number.parseInt(lines[headerIdx].match(/Skipped\s+(\d+)/i)?.[1] ?? "0", 10) || 0;
60
59
  const specifiers = lines
61
60
  .slice(headerIdx + 1)
62
61
  .map((l) => l.trim())
@@ -203,9 +202,7 @@ export class DependencyChecker {
203
202
  // next time the registry is walked.
204
203
  static instances = new Set();
205
204
  constructor(verbose = false) {
206
- this.log = verbose
207
- ? createSubsystemLogger("deps")
208
- : () => { };
205
+ this.log = verbose ? createSubsystemLogger("deps") : () => { };
209
206
  DependencyChecker.instances.add(new WeakRef(this));
210
207
  }
211
208
  /** Drop this instance's memoized madge resolution for every project root. */
@@ -435,7 +432,9 @@ export class DependencyChecker {
435
432
  const cached = this.importCache.get(normalized);
436
433
  // Fast path: neither mtime NOR size moved (#1105 — size guards the
437
434
  // mtime-preserving content change that mtime alone would miss).
438
- if (cached && cached.timestamp >= stat.mtimeMs && cached.size === stat.size) {
435
+ if (cached &&
436
+ cached.timestamp >= stat.mtimeMs &&
437
+ cached.size === stat.size) {
439
438
  return false;
440
439
  }
441
440
  // Compare actual imports
@@ -567,7 +566,12 @@ export class DependencyChecker {
567
566
  if (skips.local.length > 0) {
568
567
  this.log(`madge skipped ${skips.local.length} local file(s) (possible silent cycle-miss): ${skips.local.slice(0, 5).join(", ")}`);
569
568
  }
570
- return { ok: true, circular, circularFiles, localSkips: skips.local.length };
569
+ return {
570
+ ok: true,
571
+ circular,
572
+ circularFiles,
573
+ localSkips: skips.local.length,
574
+ };
571
575
  }
572
576
  catch (err) {
573
577
  this.log(`Check error: ${err.message}`);
@@ -171,6 +171,35 @@ export function _setBeforeDispositionCacheRefreshForTests(hook) {
171
171
  export function _setDispositionStatForTests(statSync) {
172
172
  dispositionStatSync = statSync ?? fs.statSync;
173
173
  }
174
+ /**
175
+ * Zero-I/O guard for cache-only callers (lens_diagnostics delta/all): true
176
+ * when ANY disposition mark or session defer exists, so a caller can skip its
177
+ * whole strict/weak filter — including every file stat/read the strict branch
178
+ * would need — in the overwhelmingly common no-marks case. Same hoist shape as
179
+ * applyDispositionsMultiFile's #1625 F2 empty-store early return; `readState`
180
+ * is mtime+size stat-cached, so repeated calls cost one stat.
181
+ */
182
+ export function hasAnyDispositionMarks(cwd) {
183
+ return Boolean(readState(cwd).dispositions) || deferredThisSession.size > 0;
184
+ }
185
+ /**
186
+ * True when the project's disposition store holds at least one STRICT-anchored
187
+ * `false-positive` mark — the only disposition kind whose immediate application
188
+ * needs file content. A store with only weak suppress/defer marks can never
189
+ * produce a strict-anchor match, so cache-only callers can serve them through
190
+ * the zero-I/O weak filter and skip every stat/read the strict path would
191
+ * charge.
192
+ */
193
+ export function hasStrictDispositionMarks(cwd) {
194
+ const dispositions = readState(cwd).dispositions;
195
+ if (!dispositions)
196
+ return false;
197
+ for (const key of Object.keys(dispositions)) {
198
+ if (dispositions[key]?.disposition === "false-positive")
199
+ return true;
200
+ }
201
+ return false;
202
+ }
174
203
  // Test seam for `applyDispositionsMultiFile`'s per-group content read (#1625
175
204
  // F2) — Vitest can't `vi.spyOn` a bare ESM `node:fs` named export directly
176
205
  // ("Module namespace is not configurable in ESM"), so the F2 regression test
@@ -191,7 +220,13 @@ function readState(cwd) {
191
220
  return stateCache.state;
192
221
  }
193
222
  const empty = {};
194
- stateCache = { path: p, missing: true, mtimeMs: -1, size: -1, state: empty };
223
+ stateCache = {
224
+ path: p,
225
+ missing: true,
226
+ mtimeMs: -1,
227
+ size: -1,
228
+ state: empty,
229
+ };
195
230
  return empty;
196
231
  }
197
232
  if (stateCache &&
@@ -205,7 +240,9 @@ function readState(cwd) {
205
240
  try {
206
241
  const parsed = JSON.parse(fs.readFileSync(p, "utf-8"));
207
242
  state =
208
- parsed && typeof parsed === "object" ? parsed : {};
243
+ parsed && typeof parsed === "object"
244
+ ? parsed
245
+ : {};
209
246
  }
210
247
  catch {
211
248
  // Now that writeState is tmp+rename atomic, a torn read (another process
@@ -228,7 +228,11 @@ export function demotePastEofDiagnostics(args) {
228
228
  return d; // no transition either direction
229
229
  if (isPastEof)
230
230
  risingEdgeLines.push(d.line);
231
- return { ...d, stale: isPastEof, staleReason: isPastEof ? "past-eof" : undefined };
231
+ return {
232
+ ...d,
233
+ stale: isPastEof,
234
+ staleReason: isPastEof ? "past-eof" : undefined,
235
+ };
232
236
  });
233
237
  if (risingEdgeLines.length === 0) {
234
238
  return { diagnostics: out, demotedCount: 0 };
@@ -55,8 +55,7 @@ export function isNosemgrepSuppressed(d, content) {
55
55
  .includes(ruleId);
56
56
  };
57
57
  // The finding's own line (inline OK), then the line above (standalone comment only).
58
- return (checkLine(lines[startLine], false) ||
59
- checkLine(lines[startLine - 1], true));
58
+ return (checkLine(lines[startLine], false) || checkLine(lines[startLine - 1], true));
60
59
  }
61
60
  /**
62
61
  * zizmor's own native inline suppression: `# zizmor: ignore[audit-id[,audit-id]]`
@@ -91,7 +90,7 @@ export function isZizmorIgnoreSuppressed(d, content) {
91
90
  // findings block only when the workspace opted into curated/authored rules;
92
91
  // everything else stays advisory) — shared here instead of copy-pasted per
93
92
  // profile so a future policy change (e.g. a WARNING-blocking tier) is one edit.
94
- const blockOnErrorWhenAllowed = (d, { blockingAllowed }) => (blockingAllowed && d.severity === 1 ? "blocking" : "warning");
93
+ const blockOnErrorWhenAllowed = (d, { blockingAllowed }) => blockingAllowed && d.severity === 1 ? "blocking" : "warning";
95
94
  export const AUXILIARY_LSP_PROFILES = [
96
95
  {
97
96
  serverId: "opengrep",
@@ -36,6 +36,7 @@ import { getToolPlan } from "./plan.js";
36
36
  import { resolveRunnerPath } from "./runner-context.js";
37
37
  import { applyRulePolicy, rulePolicyMapFromConfig } from "./rule-policy.js";
38
38
  import { getToolProfile } from "./tool-profile.js";
39
+ import { isRunnerSkipReason } from "./types.js";
39
40
  import { formatDiagnostics } from "./utils/format-utils.js";
40
41
  // --- Runner Registry ---
41
42
  export class RunnerRegistry {
@@ -606,6 +607,12 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
606
607
  onRunnerResult?.(runnerId, result);
607
608
  const runnerEnd = Date.now();
608
609
  const duration = runnerEnd - runnerStart;
610
+ // Runner definitions are a typed API, but embedders/plugins can still
611
+ // return untyped objects at runtime. Admit only the closed taxonomy and
612
+ // only on actual skips so free text cannot enter durable latency metadata.
613
+ const skipReason = result.status === "skipped" && isRunnerSkipReason(result.skipReason)
614
+ ? result.skipReason
615
+ : undefined;
609
616
  latencies.push({
610
617
  runnerId,
611
618
  startTime: runnerStart,
@@ -614,6 +621,9 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
614
621
  status: result.status,
615
622
  diagnosticCount: result.diagnostics.length,
616
623
  semantic: result.semantic ?? semantic,
624
+ ...(skipReason !== undefined && {
625
+ skipReason,
626
+ }),
617
627
  ...(result.unconfirmedServerIds !== undefined && {
618
628
  unconfirmedServerIds: result.unconfirmedServerIds,
619
629
  }),
@@ -640,7 +650,9 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
640
650
  failureKind: result.failureKind,
641
651
  failureMessage: result.failureMessage,
642
652
  }
643
- : undefined,
653
+ : skipReason
654
+ ? { skipReason }
655
+ : undefined,
644
656
  });
645
657
  recordRunner(ctx.filePath, runnerId, result.status, result.diagnostics.length, duration, ctx.writeIndex);
646
658
  diagnostics.push(...result.diagnostics);
@@ -76,7 +76,9 @@ function parameterName(param) {
76
76
  // JavaScript's grammar keeps a leaf parameter as the identifier itself;
77
77
  // there is no named child to unwrap. TypeScript parameter wrapper nodes still
78
78
  // use their first named child (type annotation/default/rest target).
79
- return param.type === "identifier" ? param.text : firstNamedChild(param)?.text ?? "";
79
+ return param.type === "identifier"
80
+ ? param.text
81
+ : (firstNamedChild(param)?.text ?? "");
80
82
  }
81
83
  function getFunctionName(node) {
82
84
  if (node.type === "function_declaration") {
@@ -122,7 +122,8 @@ export const importFactProvider = {
122
122
  if (callee?.type === "import") {
123
123
  dynamicRaw.push({ source, kind: "import" });
124
124
  }
125
- else if (callee?.type === "identifier" && callee.text === "require") {
125
+ else if (callee?.type === "identifier" &&
126
+ callee.text === "require") {
126
127
  dynamicRaw.push({ source, kind: "require" });
127
128
  hasCjs = true;
128
129
  }
@@ -8,7 +8,7 @@
8
8
  * shell.
9
9
  */
10
10
  import { childrenOfType, firstChildOfType, withTreeSitterRoot, walk, } from "../../tree-sitter-shared.js";
11
- export { childrenOfType, firstChildOfType, walk, };
11
+ export { childrenOfType, firstChildOfType, walk };
12
12
  export const withFactTree = withTreeSitterRoot;
13
13
  /**
14
14
  * Provider shell for tree-sitter-backed fact extractors: read `file.content`,
@@ -789,7 +789,8 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
789
789
  action: "reused_unchanged",
790
790
  savedToSnapshot: reverseDepsSaved,
791
791
  importsFileCount: Object.keys(reverseDepsIndex.imports).length,
792
- importedByFileCount: Object.keys(reverseDepsIndex.importedBy).length,
792
+ importedByFileCount: Object.keys(reverseDepsIndex.importedBy)
793
+ .length,
793
794
  },
794
795
  });
795
796
  }
@@ -841,7 +842,8 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
841
842
  action: "refresh_from_review_graph",
842
843
  savedToSnapshot: reverseDepsSaved,
843
844
  importsFileCount: Object.keys(reverseDepsIndex.imports).length,
844
- importedByFileCount: Object.keys(reverseDepsIndex.importedBy).length,
845
+ importedByFileCount: Object.keys(reverseDepsIndex.importedBy)
846
+ .length,
845
847
  importEdgeCount: Object.values(reverseDepsIndex.imports).reduce((total, imports) => total + imports.length, 0),
846
848
  },
847
849
  });
@@ -1517,7 +1519,9 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
1517
1519
  // #1179: `.filter()` here operates on `rawDiags.diags`; the
1518
1520
  // `inconclusive`/`binding` flags read above stay on the `rawDiags`
1519
1521
  // wrapper and are unaffected by this copy (the shape-5 fix).
1520
- const diags = convertLspDiagnostics(rawDiags.diags.filter((d) => d.severity === 1).slice(0, MAX_PER_FILE), neighborPath);
1522
+ const diags = convertLspDiagnostics(rawDiags.diags
1523
+ .filter((d) => d.severity === 1)
1524
+ .slice(0, MAX_PER_FILE), neighborPath);
1521
1525
  const durationMs = Date.now() - neighborStart;
1522
1526
  // #1899: the A5 same-write cache write stood here.
1523
1527
  if (diags.length === 0) {
@@ -1827,7 +1831,8 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
1827
1831
  if (entry.idleTimer !== undefined)
1828
1832
  clearTimeout(entry.idleTimer);
1829
1833
  entry.idleTimer = undefined;
1830
- if (!reverseDepsTimersToRelease.has(key) && reverseDepsEntriesAtStart.has(entry)) {
1834
+ if (!reverseDepsTimersToRelease.has(key) &&
1835
+ reverseDepsEntriesAtStart.has(entry)) {
1831
1836
  reverseDepsTimersToRelease.add(key);
1832
1837
  }
1833
1838
  }
@@ -10,7 +10,9 @@ export const errorSwallowingRule = {
10
10
  return [];
11
11
  const diagnostics = [];
12
12
  for (const s of summaries) {
13
- if (s.isEmpty && !s.isDocumentedLocalFallback && s.boundaryCategory !== "fs") {
13
+ if (s.isEmpty &&
14
+ !s.isDocumentedLocalFallback &&
15
+ s.boundaryCategory !== "fs") {
14
16
  diagnostics.push({
15
17
  id: `error-swallowing:${ctx.filePath}:${s.line}:${s.column}`,
16
18
  tool: "fact-rules",
@@ -1,7 +1,9 @@
1
1
  import { isTestFile } from "../../file-utils.js";
2
2
  const ALIAS_COMMENT_RE = /\b(alias|backward\s*compat|backwards\s*compat|compatibility|shim|adapter)\b/i;
3
3
  function hasAliasCommentNear(line, comments) {
4
- return comments.some((comment) => comment.line >= line - 2 && comment.line <= line && ALIAS_COMMENT_RE.test(comment.text));
4
+ return comments.some((comment) => comment.line >= line - 2 &&
5
+ comment.line <= line &&
6
+ ALIAS_COMMENT_RE.test(comment.text));
5
7
  }
6
8
  export const passThroughWrappersRule = {
7
9
  id: "pass-through-wrappers",
@@ -16,7 +18,9 @@ export const passThroughWrappersRule = {
16
18
  return [];
17
19
  const diagnostics = [];
18
20
  for (const fn of summaries) {
19
- if (!fn.isPassThroughWrapper || fn.statementCount !== 1 || fn.isBoundaryWrapper) {
21
+ if (!fn.isPassThroughWrapper ||
22
+ fn.statementCount !== 1 ||
23
+ fn.isBoundaryWrapper) {
20
24
  continue;
21
25
  }
22
26
  if (hasAliasCommentNear(fn.line, comments))
@@ -10,16 +10,40 @@
10
10
  // All other entries are exact callee names — prevents e.g. "spawn" matching "spawned.map"
11
11
  // or "fetch" matching "fetchWithRetry".
12
12
  const IO_NAMESPACE_PREFIXES = [
13
- "db.", "prisma.", "knex.", "mongoose.", "sequelize.",
14
- "http.", "https.", "net.", "dns.",
15
- "redis.", "mongo.", "pg.", "mysql.",
16
- "s3.", "storage.", "bucket.",
13
+ "db.",
14
+ "prisma.",
15
+ "knex.",
16
+ "mongoose.",
17
+ "sequelize.",
18
+ "http.",
19
+ "https.",
20
+ "net.",
21
+ "dns.",
22
+ "redis.",
23
+ "mongo.",
24
+ "pg.",
25
+ "mysql.",
26
+ "s3.",
27
+ "storage.",
28
+ "bucket.",
17
29
  "fs.promises.",
18
30
  ];
19
31
  const IO_EXACT_CALLEES = new Set([
20
- "fetch", "axios", "got", "request",
21
- "spawn", "exec", "execSync", "spawnSync",
22
- "readFile", "writeFile", "appendFile", "readdir", "mkdir", "unlink", "stat",
32
+ "fetch",
33
+ "axios",
34
+ "got",
35
+ "request",
36
+ "spawn",
37
+ "exec",
38
+ "execSync",
39
+ "spawnSync",
40
+ "readFile",
41
+ "writeFile",
42
+ "appendFile",
43
+ "readdir",
44
+ "mkdir",
45
+ "unlink",
46
+ "stat",
23
47
  ]);
24
48
  const CC_THRESHOLD = 6; // raised from 4 — avoids flagging simple async wrappers with one IO call
25
49
  function callsToBoundary(outgoingCalls) {
@@ -12,7 +12,10 @@ function toDiagnostic(issue, filePath) {
12
12
  const column = issue.column && issue.column > 0 ? issue.column : 1;
13
13
  const rule = issue.kind || "actionlint";
14
14
  const message = issue.message || "GitHub Actions workflow issue";
15
- const idMessage = message.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 80);
15
+ const idMessage = message
16
+ .toLowerCase()
17
+ .replace(/[^a-z0-9]+/g, "-")
18
+ .slice(0, 80);
16
19
  return {
17
20
  id: `actionlint-${rule}-${line}-${column}-${idMessage}`,
18
21
  message,
@@ -66,7 +69,7 @@ const actionlintRunner = {
66
69
  async run(ctx) {
67
70
  const cwd = ctx.cwd || process.cwd();
68
71
  let cmd = null;
69
- if (await (actionlint.isAvailableAsync(cwd))) {
72
+ if (await actionlint.isAvailableAsync(cwd)) {
70
73
  cmd = actionlint.getCommand(cwd);
71
74
  }
72
75
  else {
@@ -12,6 +12,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
12
12
  import { biomeConfigArgs, getAutofixCapability, getJstsLintPolicyForCwd, } from "../../tool-policy.js";
13
13
  import { PRIORITY } from "../priorities.js";
14
14
  import { resolveToolCommandWithInstallFallback } from "./utils/runner-helpers.js";
15
+ import { finishParsedRun } from "./utils/tool-failure.js";
15
16
  /**
16
17
  * Map biome's own severity vocabulary onto the four-tier `Diagnostic.severity`
17
18
  * (clients/dispatch/types.ts), the same way `normalizeRuleSeverity` does for
@@ -254,7 +255,9 @@ const biomeCheckJsonRunner = {
254
255
  diagnostics: [
255
256
  {
256
257
  id: "biome:parse-error:1",
257
- message: "Biome JSON parse failed: " + parsed.parseError + (preview ? " (output preview: " + preview + ")" : ""),
258
+ message: "Biome JSON parse failed: " +
259
+ parsed.parseError +
260
+ (preview ? " (output preview: " + preview + ")" : ""),
258
261
  filePath: ctx.filePath,
259
262
  line: 1,
260
263
  column: 1,
@@ -266,19 +269,12 @@ const biomeCheckJsonRunner = {
266
269
  semantic: "warning",
267
270
  };
268
271
  }
269
- const diagnostics = parsed.diagnostics;
270
- let semantic = "none";
271
- if (diagnostics.some((d) => d.semantic === "blocking")) {
272
- semantic = "blocking";
273
- }
274
- else if (diagnostics.length > 0) {
275
- semantic = "warning";
276
- }
277
- return {
278
- status: semantic === "blocking" ? "failed" : "succeeded",
279
- diagnostics,
280
- semantic,
281
- };
272
+ return finishParsedRun({
273
+ tool: "biome",
274
+ ctx,
275
+ result: checkResult,
276
+ diagnostics: parsed.diagnostics,
277
+ });
282
278
  },
283
279
  };
284
280
  export default biomeCheckJsonRunner;
@@ -91,7 +91,11 @@ async function resolveCompiler(absPath, cwd) {
91
91
  const clCmd = clChecker.getCommand(cwd);
92
92
  if (clCmd) {
93
93
  // Already probed in a previous turn and resolved.
94
- return { command: clCmd, args: ["/nologo", "/Zs", absPath], flavor: "msvc" };
94
+ return {
95
+ command: clCmd,
96
+ args: ["/nologo", "/Zs", absPath],
97
+ flavor: "msvc",
98
+ };
95
99
  }
96
100
  const clProbe = await safeSpawnAsync("cl", [], { timeout: 5000 });
97
101
  if (!clProbe.error && clProbe.status !== null) {
@@ -120,7 +120,7 @@ const dotnetBuildRunner = {
120
120
  skipTestFiles: false,
121
121
  async run(ctx) {
122
122
  const cwd = ctx.cwd || process.cwd();
123
- if (!(await (dotnet.isAvailableAsync(cwd)))) {
123
+ if (!(await dotnet.isAvailableAsync(cwd))) {
124
124
  return { status: "skipped", diagnostics: [], semantic: "none" };
125
125
  }
126
126
  const cmd = dotnet.getCommand(cwd);
@@ -88,7 +88,9 @@ function parseElixirOutput(raw, filePath, cwd = process.cwd()) {
88
88
  if (matchesTarget(sourcePath)) {
89
89
  diagnostics.push({
90
90
  id: `elixir-check-${severity}-${lineStr}-${colStr || "1"}`,
91
- message: severity === "error" ? `[error] ${message.trim()}` : message.trim(),
91
+ message: severity === "error"
92
+ ? `[error] ${message.trim()}`
93
+ : message.trim(),
92
94
  filePath,
93
95
  line: Number.parseInt(lineStr, 10) || 1,
94
96
  column: Number.parseInt(colStr || "1", 10) || 1,
@@ -88,13 +88,22 @@ const eslintRunner = {
88
88
  return { status: "skipped", diagnostics: [], semantic: "none" };
89
89
  }
90
90
  const result = await safeSpawnAsync(cmd, ["--format", "json", "--no-error-on-unmatched-pattern", ctx.filePath], { timeout: 30000, cwd });
91
- // ESLint exits 1 when there are lint errors, 2 on fatal/config error
91
+ // ESLint exits 2 on fatal/config errors — nothing was linted, so this
92
+ // is an unavailable run, not a clean or failed one.
92
93
  if (result.status === 2) {
93
94
  return { status: "skipped", diagnostics: [], semantic: "none" };
94
95
  }
95
- const raw = result.stdout || result.stderr || "";
96
- if (result.status === 0) {
97
- return { status: "succeeded", diagnostics: [], semantic: "none" };
96
+ // ESLint exits 0 whenever nothing reached ERROR severity — that
97
+ // includes a run that found only warnings (#1954), which also prints a
98
+ // full JSON report. So parse stdout unconditionally and branch on the
99
+ // parsed diagnostic count instead of letting the exit code discard the
100
+ // warning case. Stderr is only a fallback for a failing run whose
101
+ // stdout went missing; parsing stderr noise on a healthy exit-0 run
102
+ // would turn deprecation chatter into spurious parse-error findings.
103
+ const stdout = result.stdout ?? "";
104
+ let raw = stdout;
105
+ if (raw.length === 0 && result.status !== 0) {
106
+ raw = result.stderr || "";
98
107
  }
99
108
  const parsed = parseEslintJson(raw, ctx.filePath);
100
109
  if (parsed.parseError && raw.trim().length > 0) {
@@ -104,7 +113,9 @@ const eslintRunner = {
104
113
  diagnostics: [
105
114
  {
106
115
  id: "eslint:parse-error:1",
107
- message: "ESLint JSON parse failed: " + parsed.parseError + (preview ? " (output preview: " + preview + ")" : ""),
116
+ message: "ESLint JSON parse failed: " +
117
+ parsed.parseError +
118
+ (preview ? " (output preview: " + preview + ")" : ""),
108
119
  filePath: ctx.filePath,
109
120
  line: 1,
110
121
  column: 1,
@@ -121,8 +132,16 @@ const eslintRunner = {
121
132
  return { status: "succeeded", diagnostics: [], semantic: "none" };
122
133
  }
123
134
  const hasErrors = diagnostics.some((d) => d.semantic === "blocking");
135
+ // A warning-only result on exit 0 is ESLint's normal outcome, not a
136
+ // failure: exit 0 means nothing hit ERROR severity. Keying status off
137
+ // blocking severity plus exit code (the sibling convention from oxlint,
138
+ // biome-check, golangci-lint, rubocop) keeps plan.ts's fallback group
139
+ // ["eslint", "oxlint", "biome-check-json"] stopping at eslint instead
140
+ // of re-running oxlint and biome-check-json on every warning-only save.
141
+ // The findings reach delivery regardless of status — dispatcher.ts
142
+ // buckets by each diagnostic's own `semantic`.
124
143
  return {
125
- status: "failed",
144
+ status: !hasErrors && result.status === 0 ? "succeeded" : "failed",
126
145
  diagnostics,
127
146
  semantic: hasErrors ? "blocking" : "warning",
128
147
  };
@@ -11,7 +11,7 @@ const fishIndentRunner = {
11
11
  skipTestFiles: false,
12
12
  async run(ctx) {
13
13
  const cwd = ctx.cwd || process.cwd();
14
- const available = await (fishIndent.isAvailableAsync(cwd));
14
+ const available = await fishIndent.isAvailableAsync(cwd);
15
15
  if (!available)
16
16
  return { status: "skipped", diagnostics: [], semantic: "none" };
17
17
  const cmd = fishIndent.getCommand(cwd);
@@ -43,7 +43,7 @@ const gleamCheckRunner = {
43
43
  skipTestFiles: false,
44
44
  async run(ctx) {
45
45
  const cwd = ctx.cwd || process.cwd();
46
- if (!(await (gleam.isAvailableAsync(cwd)))) {
46
+ if (!(await gleam.isAvailableAsync(cwd))) {
47
47
  return { status: "skipped", diagnostics: [], semantic: "none" };
48
48
  }
49
49
  const cmd = gleam.getCommand(cwd);
@@ -31,7 +31,9 @@ function describeReplacement(replacement) {
31
31
  return "Delete this code";
32
32
  if (replacement.NewLines && replacement.NewLines.length > 0) {
33
33
  const preview = replacement.NewLines[0].trim();
34
- const hint = replacement.NewLines.length > 1 ? ` (+${replacement.NewLines.length - 1} more lines)` : "";
34
+ const hint = replacement.NewLines.length > 1
35
+ ? ` (+${replacement.NewLines.length - 1} more lines)`
36
+ : "";
35
37
  return `Replace with: ${preview}${hint}`;
36
38
  }
37
39
  return "Apply golangci-lint suggested fix";
@@ -4,6 +4,7 @@ import { getLinterPolicyForCwd } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
6
  import { parseToolRun } from "./utils/tool-failure.js";
7
+ import { finishParsedRun } from "./utils/tool-failure.js";
7
8
  const hadolint = createAvailabilityChecker("hadolint", ".exe");
8
9
  function parseHadolintOutput(raw, filePath) {
9
10
  try {
@@ -60,15 +61,19 @@ const hadolintRunner = {
60
61
  if (run.skipped)
61
62
  return run.skipped;
62
63
  const diagnostics = run.diagnostics;
63
- if (diagnostics.length === 0) {
64
- return { status: "succeeded", diagnostics: [], semantic: "none" };
65
- }
66
- const hasErrors = diagnostics.some((d) => d.severity === "error");
67
- return {
68
- status: "failed",
64
+ return finishParsedRun({
65
+ tool: "hadolint",
66
+ ctx,
67
+ result,
69
68
  diagnostics,
70
- semantic: hasErrors ? "blocking" : "warning",
71
- };
69
+ classify: (diagnostics) => {
70
+ const hasErrors = diagnostics.some((d) => d.severity === "error");
71
+ return {
72
+ status: "failed",
73
+ semantic: hasErrors ? "blocking" : "warning",
74
+ };
75
+ },
76
+ });
72
77
  },
73
78
  };
74
79
  export default hadolintRunner;
@@ -15,7 +15,10 @@ const SKIPPED = {
15
15
  };
16
16
  function isWithin(root, candidate) {
17
17
  const relative = path.relative(normalizeMapKey(root), normalizeMapKey(candidate));
18
- return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
18
+ return (relative === "" ||
19
+ (!relative.startsWith(`..${path.sep}`) &&
20
+ relative !== ".." &&
21
+ !path.isAbsolute(relative)));
19
22
  }
20
23
  function diagnosticLocation(message, chartRoot) {
21
24
  const location = message.match(/(?:^|\s)([^:\r\n]+\.(?:ya?ml|tpl|json))(?::(\d+))?(?::\d+)?(?::|\s)/i);
@@ -4,6 +4,7 @@ import { getLinterPolicyForCwd } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
6
  import { parseToolRun } from "./utils/tool-failure.js";
7
+ import { finishParsedRun } from "./utils/tool-failure.js";
7
8
  const htmlhint = createAvailabilityChecker("htmlhint");
8
9
  const HTMLHINT_RULES = {
9
10
  "tag-pair": true,
@@ -64,10 +65,20 @@ const htmlhintRunner = {
64
65
  if (!cmd) {
65
66
  return { status: "skipped", diagnostics: [], semantic: "none" };
66
67
  }
67
- const rulesJson = JSON.stringify(HTMLHINT_RULES);
68
+ // htmlhint's --rules flag takes a comma-separated ruleid list
69
+ // ("tag-pair,id-class-value=underline"), NOT a JSON object. The old JSON
70
+ // blob parsed as one bogus rule id, leaving ZERO rules enabled — every
71
+ // file read CLEAN (exit 0, no output) no matter what it contained.
72
+ // Root-caused live against htmlhint 1.x after the tier-1 parser smoke
73
+ // caught htmlhint reporting 0 findings on the planted tag-pair defect.
74
+ // Entries set to false are omitted: under --rules semantics an unlisted
75
+ // rule is off, which is exactly what `false` means here.
76
+ const rulesArg = Object.entries(HTMLHINT_RULES)
77
+ .flatMap(([rule, enabled]) => (enabled === true ? [rule] : []))
78
+ .join(",");
68
79
  const result = await safeSpawnAsync(cmd, [
69
80
  "--rules",
70
- rulesJson,
81
+ rulesArg,
71
82
  "--format",
72
83
  "unix",
73
84
  path.resolve(cwd, ctx.filePath),
@@ -79,15 +90,19 @@ const htmlhintRunner = {
79
90
  if (run.skipped)
80
91
  return run.skipped;
81
92
  const diagnostics = run.diagnostics;
82
- if (diagnostics.length === 0) {
83
- return { status: "succeeded", diagnostics: [], semantic: "none" };
84
- }
85
- const hasErrors = diagnostics.some((d) => d.severity === "error");
86
- return {
87
- status: "failed",
93
+ return finishParsedRun({
94
+ tool: "htmlhint",
95
+ ctx,
96
+ result,
88
97
  diagnostics,
89
- semantic: hasErrors ? "blocking" : "warning",
90
- };
98
+ classify: (diagnostics) => {
99
+ const hasErrors = diagnostics.some((d) => d.severity === "error");
100
+ return {
101
+ status: "failed",
102
+ semantic: hasErrors ? "blocking" : "warning",
103
+ };
104
+ },
105
+ });
91
106
  },
92
107
  };
93
108
  export default htmlhintRunner;