@herbertgao/pi-extensions 2026.9.5 → 2026.9.7

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 (276) hide show
  1. package/README.md +5 -22
  2. package/THIRD_PARTY_NOTICES.md +0 -4
  3. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +1 -1
  4. package/node_modules/@herbertgao/sol-pi/package.json +1 -1
  5. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +0 -5
  6. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +3 -1
  7. package/node_modules/@narumitw/pi-btw/README.md +2 -0
  8. package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
  9. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  10. package/node_modules/@narumitw/pi-btw/package.json +52 -53
  11. package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
  12. package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
  13. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
  14. package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
  15. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
  16. package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
  17. package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
  18. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
  19. package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
  20. package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
  21. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
  22. package/node_modules/pi-lens/CHANGELOG.md +239 -0
  23. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
  24. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
  25. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
  26. package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
  27. package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
  28. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
  29. package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
  30. package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
  31. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
  32. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
  33. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
  34. package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
  35. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
  36. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
  37. package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
  38. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
  39. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
  40. package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
  41. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
  42. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
  43. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
  44. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
  45. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
  46. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
  47. package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
  48. package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
  49. package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
  50. package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
  51. package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
  52. package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
  53. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
  54. package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
  55. package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
  56. package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
  57. package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
  58. package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
  59. package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
  60. package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
  61. package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
  62. package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
  63. package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
  64. package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
  65. package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
  66. package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
  67. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
  68. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
  69. package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
  70. package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
  71. package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
  72. package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
  73. package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
  74. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
  75. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
  76. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
  77. package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
  78. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
  79. package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
  80. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
  81. package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
  82. package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
  83. package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
  84. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
  85. package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
  86. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
  87. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
  88. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
  89. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
  90. package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
  91. package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
  92. package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
  93. package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
  94. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
  95. package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
  96. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
  97. package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
  98. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
  99. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
  100. package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
  101. package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
  102. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
  103. package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
  104. package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
  105. package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
  106. package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
  107. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
  108. package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
  109. package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
  110. package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
  111. package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
  112. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
  113. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
  114. package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
  115. package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
  116. package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
  117. package/node_modules/pi-lens/dist/index.js +27416 -24153
  118. package/node_modules/pi-lens/dist/mcp/server.js +5 -2
  119. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
  120. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
  121. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
  122. package/node_modules/pi-lens/docs/audit1.md +5 -5
  123. package/node_modules/pi-lens/docs/dependencies.md +11 -0
  124. package/node_modules/pi-lens/docs/dispositions.md +52 -0
  125. package/node_modules/pi-lens/docs/environment-variables.md +2 -2
  126. package/node_modules/pi-lens/docs/features.md +4 -4
  127. package/node_modules/pi-lens/docs/globalconfig.md +3 -1
  128. package/node_modules/pi-lens/docs/language-coverage.md +1 -0
  129. package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
  130. package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
  131. package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
  132. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
  133. package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
  134. package/node_modules/pi-lens/docs/settings.md +7 -4
  135. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
  136. package/node_modules/pi-lens/docs/usage.md +2 -0
  137. package/node_modules/pi-lens/package.json +1 -1
  138. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
  139. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
  140. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
  141. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
  142. package/package.json +6 -17
  143. package/examples/pi-footer.json +0 -275
  144. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +0 -70
  145. package/node_modules/@czottmann/pi-automode/LICENSE.md +0 -21
  146. package/node_modules/@czottmann/pi-automode/README.md +0 -215
  147. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +0 -39
  148. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +0 -46
  149. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +0 -60
  150. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +0 -6
  151. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +0 -428
  152. package/node_modules/@czottmann/pi-automode/docs/configuration.md +0 -171
  153. package/node_modules/@czottmann/pi-automode/docs/defaults.md +0 -178
  154. package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +0 -90
  155. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +0 -160
  156. package/node_modules/@czottmann/pi-automode/examples/automode.local.json +0 -44
  157. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +0 -692
  158. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +0 -852
  159. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +0 -904
  160. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +0 -228
  161. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +0 -954
  162. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +0 -429
  163. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +0 -173
  164. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model-selector.ts +0 -113
  165. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model.ts +0 -13
  166. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +0 -297
  167. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +0 -623
  168. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +0 -102
  169. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/transcript.ts +0 -236
  170. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +0 -205
  171. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +0 -54
  172. package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +0 -26
  173. package/node_modules/@czottmann/pi-automode/package.json +0 -61
  174. package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +0 -63
  175. package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
  176. package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
  177. package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
  178. package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
  179. package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
  180. package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
  181. package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
  182. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
  183. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
  184. package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +0 -54
  185. package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
  186. package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
  187. package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
  188. package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
  189. package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
  190. package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
  191. package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
  192. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
  193. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
  194. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
  195. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
  196. package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
  197. package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
  198. package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
  199. package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
  200. package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
  201. package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
  202. package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
  203. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
  204. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
  205. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
  206. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
  207. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
  208. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
  209. package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
  210. package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
  211. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
  212. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
  213. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
  214. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
  215. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
  216. package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
  217. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
  218. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
  219. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
  220. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
  221. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
  222. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
  223. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
  224. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
  225. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
  226. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
  227. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
  228. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
  229. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
  230. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
  231. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
  232. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
  233. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
  234. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
  235. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
  236. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
  237. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
  238. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
  239. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
  240. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
  241. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
  242. package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
  243. package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
  244. package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
  245. package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
  246. package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
  247. package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
  248. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
  249. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
  250. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
  251. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
  252. package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
  253. package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
  254. package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
  255. package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
  256. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
  257. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
  258. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
  259. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
  260. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
  261. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
  262. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
  263. package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
  264. package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
  265. package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
  266. package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
  267. package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
  268. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
  269. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
  270. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
  271. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
  272. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
  273. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
  274. package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
  275. package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
  276. package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
@@ -969,7 +969,8 @@ async function callTool(name, args) {
969
969
  summaryLines.push(truncationNotice);
970
970
  // #1107 phase 2: same "reached the seam but nothing rendered it" gap as
971
971
  // #784's scanTruncationNotice, for the generated-name skip counters.
972
- const skipNotice = generatedSkipNotice(snapshot);
972
+ // #2535: render the MCP-callable tool names on this route.
973
+ const skipNotice = generatedSkipNotice(snapshot, "mcp");
973
974
  if (skipNotice)
974
975
  summaryLines.push(skipNotice);
975
976
  return toolText(summaryLines.join("\n"), {
@@ -1375,7 +1376,9 @@ async function callTool(name, args) {
1375
1376
  if (name === "pilens_diagnostics") {
1376
1377
  const cwd = typeof args.cwd === "string" ? args.cwd : DEFAULT_CWD;
1377
1378
  await ensureReady(cwd);
1378
- const out = (await lensDiagnosticsTool.execute("mcp", args, new AbortController().signal, undefined, { cwd }));
1379
+ const out = (await lensDiagnosticsTool.execute("mcp", args, new AbortController().signal, undefined,
1380
+ // #2535: the shared tool renders host-callable advisory names.
1381
+ { cwd, host: "mcp" }));
1379
1382
  return out;
1380
1383
  }
1381
1384
  if (name === "pilens_latency") {
@@ -46,6 +46,7 @@ import { Type } from "../clients/deps/typebox.js";
46
46
  import { markDisposition, normalizeMessage, } from "../clients/diagnostic-dispositions.js";
47
47
  import { insertSuppressComment } from "../clients/dispatch/suppress-writer.js";
48
48
  import { getFileDiagnostics, } from "../clients/widget-state.js";
49
+ import { resolveLensToolName } from "../clients/tool-config.js";
49
50
  const DISPOSITIONS = [
50
51
  "false-positive",
51
52
  "suppress",
@@ -179,7 +180,12 @@ getIdentity) {
179
180
  name: "lens_diagnostic_mark",
180
181
  label: "Mark Diagnostic",
181
182
  description: "Record a disposition for a diagnostic. Exact reported identity is required; suppress re-anchors against live diagnostics and writes an inline ignore comment, apply multiple suppressions bottom-up, and defer is session-only. Example: mark a false positive with its reported file, line, rule, and message.",
182
- promptSnippet: "Use lens_diagnostic_mark to dismiss a false-positive, suppress a won't-fix, defer, or flag a finding to fix later",
183
+ // #2535 F3: this snippet registers on pi only (`lens_diagnostic_mark`
184
+ // is declared pi-only in PI_ONLY_TOOL_REASONS — MCP has no such
185
+ // tool), so the host is pinned, not defaulted. The fallback restates
186
+ // the same pi canonical and can only fire if the registry regresses,
187
+ // which the adapter-aware guard reds on first.
188
+ promptSnippet: `Use ${resolveLensToolName("lens_diagnostic_mark", "pi") ?? "lens_diagnostic_mark"} to dismiss a false-positive, suppress a won't-fix, defer, or flag a finding to fix later`,
183
189
  parameters: Type.Object({
184
190
  filePath: Type.String({
185
191
  description: "The file the diagnostic was reported on (relative or absolute).",
@@ -16,16 +16,15 @@ import { Type } from "../clients/deps/typebox.js";
16
16
  import { anchorsForDiagnostic, applyDispositions, applyWeakDispositions, hasAnyDispositionMarks, hasStrictDispositionMarks, getDisposition, } from "../clients/diagnostic-dispositions.js";
17
17
  import { DEPENDENCY_DRIFT_MAX_DELIVERIES } from "../clients/blocker-freshness.js";
18
18
  import { freshnessFromMtime } from "../clients/freshness.js";
19
- import { applyInlineSuppressions } from "../clients/dispatch/inline-suppressions.js";
19
+ import { applyFindingPolicy, loadProjectRulePolicyMap, } from "../clients/dispatch/finding-policy.js";
20
20
  import { gateFindingsByPathFreshness } from "../clients/advisory-provenance.js";
21
21
  import { markUnreconciledFindings } from "../clients/finding-delivery-gate.js";
22
22
  import { normalizeRuleId } from "../clients/dispatch/rule-id-normalize.js";
23
- import { applyRulePolicy, rulePolicyMapFromConfig, } from "../clients/dispatch/rule-policy.js";
24
- import { loadPiLensProjectConfig } from "../clients/project-lens-config.js";
23
+ import { applyRulePolicy, } from "../clients/dispatch/rule-policy.js";
25
24
  import { compactRenderResult } from "./render-compact.js";
26
25
  import { combineAbortSignals } from "../clients/deadline-utils.js";
27
26
  import { getProjectIgnoreMatcher } from "../clients/file-utils.js";
28
- import { isAtOrAboveHomeDir, normalizeEphemeralMapKey, normalizeFilePath, } from "../clients/path-utils.js";
27
+ import { isAtOrAboveHomeDir, normalizeEphemeralMapKey, normalizeFilePath, realpathOrResolve, } from "../clients/path-utils.js";
29
28
  import { getLSPService } from "../clients/lsp/index.js";
30
29
  import { retireInlineBlockerAndResyncGuard } from "../clients/git-guard.js";
31
30
  import { primaryServerId, resolveLspCwdForFile, } from "../clients/lsp/config.js";
@@ -36,14 +35,15 @@ import { loadProjectDiagnosticsDeltaReport, loadProjectDiagnosticsSnapshot, PROJ
36
35
  import { formatCacheAgeOld, formatNotRunEntry, } from "../clients/project-diagnostics/extractors.js";
37
36
  import { ANALYZER_IDS, fetchFreshProjectDiagnostics, } from "../clients/project-diagnostics/fresh-fetch.js";
38
37
  import { loadBootstrapClients } from "../clients/bootstrap.js";
38
+ import { resolveLensToolName, } from "../clients/tool-config.js";
39
39
  import { generatedSkipNotice, scanTruncationNotice, } from "../clients/lens-engine.js";
40
40
  import { scanProjectDiagnostics } from "../clients/project-diagnostics/scanner.js";
41
41
  import { classifyDiagnosticTier, getFileDiagnosticSummaries, reconcileCorrelatedScanDiagnostics, reconcileScanDiagnostics, reconcileStaleWidgetDependencyBlockers, reconcileStaleWidgetFiles, widgetDiagnosticUri, } from "../clients/widget-state.js";
42
- import { logLatency } from "../clients/latency-logger.js";
42
+ import { claimPhaseOncePerSession, logLatency, } from "../clients/latency-logger.js";
43
43
  import { logExtension } from "../clients/extension-log.js";
44
44
  import { recordDegradationOnce } from "../clients/degradation-ledger.js";
45
45
  import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
46
- import { retagAuxiliaryDiagnostics } from "../clients/dispatch/auxiliary-lsp.js";
46
+ import { findAuxiliaryProfileForSource, retagAuxiliaryDiagnostics, } from "../clients/dispatch/auxiliary-lsp.js";
47
47
  import { detectFileRole } from "../clients/file-role.js";
48
48
  import { STALE_LINE_MARKER } from "../clients/stale-marker.js";
49
49
  import { makeProgressReporter, scanningSummaryLine } from "./scan-progress.js";
@@ -63,9 +63,13 @@ const MAX_PATHS_ENTRIES = MAX_BATCH_FILES;
63
63
  // trivy, govulncheck, dead-code, knip, jscpd, madge, opengrep, test-runner)
64
64
  // when mode=full is called without refreshRunners=cheap/all/cached — the
65
65
  // "quick mode" gate that skips the expensive fresh-fetch entirely (see
66
- // `formatFullMode`'s `analyzersPromise`). One shared string so it renders
67
- // identically everywhere it's used.
68
- const NOT_REQUESTED_REASON = "refreshRunners not requested this call (quick mode) pass refreshRunners=cheap/all/cached to lens_diagnostics mode=full to run it";
66
+ // `formatFullMode`'s `analyzersPromise`). One shared function so it renders
67
+ // identically everywhere it's used, naming the tool THIS host can call
68
+ // (#2535 F1 the shared const named the pi tool on MCP too).
69
+ function notRequestedReason(host) {
70
+ return ("refreshRunners not requested this call (quick mode) — pass " +
71
+ `refreshRunners=cheap/all/cached to ${resolveLensToolName("lens_diagnostics", host) ?? "diagnostics"} mode=full to run it`);
72
+ }
69
73
  // Wall-clock ceiling for the whole mode=full scan. Even with per-file budgets
70
74
  // and abort-signal honoring, a pathological state (a language server hanging on
71
75
  // spawn/initialize across many files) could otherwise stall the tool
@@ -314,6 +318,9 @@ captureLspStatusRepaint, getRuntime, isLensGuardEnabled = () => true) {
314
318
  includeGenerated: Type.Optional(Type.Boolean({
315
319
  description: "Include generated-name paths in full scans.",
316
320
  })),
321
+ analysisRoot: Type.Optional(Type.String({
322
+ description: "Explicit project directory for heavyweight analyzers; it must exist and resolve strictly below the home directory.",
323
+ })),
317
324
  severity: Type.Optional(Type.String({
318
325
  enum: [...LSP_SEVERITY_FILTERS],
319
326
  description: "Filter by severity threshold (default: all): error shows errors; warning includes errors and warnings; information includes errors, warnings, and information; hint and all show every known tier.",
@@ -464,6 +471,10 @@ captureLspStatusRepaint, getRuntime, isLensGuardEnabled = () => true) {
464
471
  pathsScope,
465
472
  nextWriteIndex,
466
473
  runtime: getRuntime?.(),
474
+ analysisRoot: typeof params.analysisRoot === "string"
475
+ ? params.analysisRoot
476
+ : undefined,
477
+ host: ctx.host ?? "pi",
467
478
  });
468
479
  }
469
480
  return formatDeltaMode(cacheManager, cwd, severity, pathsScope);
@@ -643,17 +654,6 @@ function filterDeltaReportDispositions(report, cwd, policyMap) {
643
654
  return report;
644
655
  return { ...report, diagnostics: policyKept };
645
656
  }
646
- /**
647
- * Load the rule-policy map from a project's `.pi-lens.json` — same source the
648
- * per-edit dispatch path uses, so a project's policy applies consistently
649
- * across every output surface. `loadPiLensProjectConfig` is mtime-cached, and
650
- * the map is filtered to entries that actually have a `disable`/`select` list
651
- * (thresholds are handled elsewhere), so the common case returns undefined and
652
- * the filter step is skipped outright.
653
- */
654
- function loadProjectRulePolicyMap(cwd) {
655
- return rulePolicyMapFromConfig(loadPiLensProjectConfig(cwd).rules);
656
- }
657
657
  /**
658
658
  * #1634 review round: `formatDeltaMode` re-serves the `actionable-warnings`/
659
659
  * `code-quality-warnings` caches verbatim — each cited `file:line`, no
@@ -1048,7 +1048,13 @@ function lspDiagnosticToWidget(diagnostic) {
1048
1048
  line: diagnostic.range.start.line + 1,
1049
1049
  col: diagnostic.range.start.character + 1,
1050
1050
  rule,
1051
- tool: "lsp",
1051
+ // #3041: keep auxiliary provenance. The footer-reconcile loop above already
1052
+ // gives a swept aux finding its real tool id via `retagAuxiliaryDiagnostics`
1053
+ // (#692); this second conversion of the SAME raw diagnostics did not, and
1054
+ // dispositions are anchored by `tool` — so a `false-positive`/`suppress`
1055
+ // mark recorded against the per-edit `ast-grep` finding never matched the
1056
+ // `lsp`-labelled copy mode=full renders.
1057
+ tool: findAuxiliaryProfileForSource(diagnostic.source)?.tool ?? "lsp",
1052
1058
  };
1053
1059
  }
1054
1060
  function projectDiagnosticToWidget(diagnostic, filePath) {
@@ -1085,6 +1091,30 @@ function diagnosticDedupKey(filePath, diagnostic) {
1085
1091
  function runnerIdOf(diagnostic) {
1086
1092
  return diagnostic.tool ?? diagnostic.rule?.split(":", 1)[0] ?? "";
1087
1093
  }
1094
+ /**
1095
+ * The one project-runner retirement decision. Coverage is authoritative when
1096
+ * present for the runner; the older id-only arm is used only when absent.
1097
+ */
1098
+ export function runnerRetirementDecision(diagnostic, filePath, authoritativeRunnerIds, authoritativeCoverage) {
1099
+ const runnerId = runnerIdOf(diagnostic);
1100
+ const coverage = (authoritativeCoverage ?? []).filter((entry) => entry.runnerId === runnerId && entry.files.size > 0);
1101
+ if (coverage.length === 0) {
1102
+ return authoritativeRunnerIds?.has(runnerId) ? "retire" : "keep";
1103
+ }
1104
+ const realFilePath = realpathOrResolve(filePath);
1105
+ for (const entry of coverage) {
1106
+ const root = entry.root;
1107
+ const relative = path.relative(root, realFilePath);
1108
+ const underRoot = relative === "" ||
1109
+ (!relative.startsWith("..") && !path.isAbsolute(relative));
1110
+ if (!underRoot)
1111
+ continue;
1112
+ if (entry.files.has(realFilePath)) {
1113
+ return "retire";
1114
+ }
1115
+ }
1116
+ return "keep";
1117
+ }
1088
1118
  function summarizeDiagnostics(filePath, diagnostics, hasFinalSnapshot) {
1089
1119
  let blocking = 0;
1090
1120
  let errors = 0;
@@ -1292,7 +1322,7 @@ function mergeDiagnosticsWithWidgetSummaries(widgetSummaries, lspResults, projec
1292
1322
  * additive behavior (fail-open: unconfirmed/timed-out sweeps never retire
1293
1323
  * widget state they did not actually re-check).
1294
1324
  */
1295
- authoritativeLspFiles, authoritativeRunnerIds) {
1325
+ authoritativeLspFiles, authoritativeRunnerIds, authoritativeRunnerCoverage) {
1296
1326
  const byFile = new Map();
1297
1327
  const seen = new Set();
1298
1328
  for (const summary of widgetSummaries) {
@@ -1307,7 +1337,7 @@ authoritativeLspFiles, authoritativeRunnerIds) {
1307
1337
  continue;
1308
1338
  const retained = summary.diagnostics ?? [];
1309
1339
  const diagnostics = retained
1310
- .filter((diagnostic) => !authoritativeRunnerIds?.has(runnerIdOf(diagnostic)))
1340
+ .filter((diagnostic) => runnerRetirementDecision(diagnostic, filePath, authoritativeRunnerIds, authoritativeRunnerCoverage) !== "retire")
1311
1341
  .map((d) => ({ ...d }));
1312
1342
  byFile.set(filePath,
1313
1343
  // #2154 v4: when the filter retires rows, the stored tallies describe
@@ -1377,17 +1407,20 @@ async function applyInlineSuppressionsToSummaries(summaries, cwd, policyMap) {
1377
1407
  ? summary
1378
1408
  : summarizeDiagnostics(summary.filePath, policyKept, summary.hasFinalSnapshot);
1379
1409
  }
1380
- const inlineKept = applyInlineSuppressions(summary.diagnostics, content);
1381
- // #690: same false-positive/suppress/defer disposition filter the
1382
- // per-edit dispatch path applies (dispatcher.ts) mode=full merges in
1383
- // diagnostics from a fresh LSP sweep/project scan that never went
1384
- // through that path, so without this a disposed finding reappears here.
1385
- const kept = applyDispositions(inlineKept, cwd, summary.filePath, content);
1386
- // Project rule policy (`.pi-lens.json` `rules.<id>.disable`/`select`).
1387
- // Applied after inline suppression / disposition so the policy's
1388
- // output-only filtering affects the same surface the per-edit path
1389
- // produces (no double-counting, no leftover policy-rejected findings).
1390
- const policyKept = applyRulePolicy(kept, policyMap);
1410
+ // #690/#3088: inline `pi-lens-ignore` → the same false-positive/
1411
+ // suppress/defer disposition filter the per-edit dispatch path applies
1412
+ // (dispatcher.ts) the project's `.pi-lens.json` rule policy. mode=full
1413
+ // merges in diagnostics from a fresh LSP sweep/project scan that never
1414
+ // went through the dispatch path, so without this a disposed finding
1415
+ // reappears here. #3088 folded the three calls onto the shared
1416
+ // `applyFindingPolicy` seam, which the `source=lsp` probe lane now calls
1417
+ // too one stack, one order, for every model-facing surface.
1418
+ const { kept: policyKept } = applyFindingPolicy(summary.diagnostics, {
1419
+ cwd,
1420
+ filePath: summary.filePath,
1421
+ content,
1422
+ policyMap,
1423
+ });
1391
1424
  // Tag `flagged` diagnostics for the render loop (formatAllMode). Content
1392
1425
  // is already in hand here (unlike mode=all/delta's cache-only path), so
1393
1426
  // this is the one place the tag can be computed without adding I/O to
@@ -1458,9 +1491,30 @@ async function getProjectDiagnosticsSnapshotForFullMode(cwd, options) {
1458
1491
  // edited/deleted since the scan so a stale entry isn't replayed (#298). A
1459
1492
  // fresh scan (above) is current by construction and needs no reconcile.
1460
1493
  const cached = loadProjectDiagnosticsSnapshot(cwd);
1461
- return cached
1462
- ? reconcileProjectDiagnosticsSnapshot(cached).snapshot
1463
- : undefined;
1494
+ if (!cached)
1495
+ return undefined;
1496
+ const reconciled = reconcileProjectDiagnosticsSnapshot(cached);
1497
+ // #2154: what this gate DROPS was invisible — the count was computed and
1498
+ // thrown away, so a session that silently retired another session's rows
1499
+ // (the whole point of the content axis added this round) left no record
1500
+ // of having done so. Bounded by construction: at most one row per
1501
+ // mode=full call, and only when rows were actually retired — the shape
1502
+ // `lsp_authoritative_widget_retire` uses for the sibling arm.
1503
+ if (reconciled.staleDropped > 0) {
1504
+ logLatency({
1505
+ type: "phase",
1506
+ toolName: "lens_diagnostics",
1507
+ filePath: cwd,
1508
+ phase: "project_snapshot_rows_retired",
1509
+ durationMs: 0,
1510
+ metadata: {
1511
+ files: reconciled.staleDropped,
1512
+ rows: cached.diagnostics.length - reconciled.snapshot.diagnostics.length,
1513
+ scannedAt: cached.scannedAt,
1514
+ },
1515
+ });
1516
+ }
1517
+ return reconciled.snapshot;
1464
1518
  }
1465
1519
  return undefined;
1466
1520
  }
@@ -1479,6 +1533,9 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1479
1533
  };
1480
1534
  }
1481
1535
  const { signal, pathsScope, nextWriteIndex } = options;
1536
+ // #2535: advisories name the delivery host's callable tools; pi callers
1537
+ // omit host and keep the pi spelling.
1538
+ const host = options.host ?? "pi";
1482
1539
  const includeFile = createScopedFileFilter(cwd, pathsScope);
1483
1540
  // `paths` (#461): route the active scans at exactly the requested files
1484
1541
  // instead of walking the whole project. Three cases:
@@ -1507,11 +1564,13 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1507
1564
  const analyzersPromise = projectRunnersRequested
1508
1565
  ? loadBootstrapClients().then((clients) => fetchFreshProjectDiagnostics(cacheManager, cwd, clients, signal, {
1509
1566
  runtime: options.runtime,
1567
+ analysisRoot: options.analysisRoot,
1510
1568
  }))
1511
1569
  : Promise.resolve({
1512
1570
  diagnostics: [],
1513
1571
  runners: [],
1514
1572
  analyzed: [],
1573
+ authoritativeCoverage: [],
1515
1574
  // #1623: every heavyweight analyzer is ELIGIBLE for this project but
1516
1575
  // this call never asked for it (refreshRunners wasn't cheap/all/
1517
1576
  // cached) — the expensive fetch below deliberately never runs in
@@ -1521,7 +1580,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1521
1580
  // truth for which lanes this covers — reuse it rather than
1522
1581
  // hand-listing ids here.
1523
1582
  cold: [...ANALYZER_IDS],
1524
- coldReasons: Object.fromEntries(ANALYZER_IDS.map((id) => [id, NOT_REQUESTED_REASON])),
1583
+ coldReasons: Object.fromEntries(ANALYZER_IDS.map((id) => [id, notRequestedReason(host)])),
1525
1584
  failed: [],
1526
1585
  timings: {},
1527
1586
  });
@@ -1540,6 +1599,17 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1540
1599
  }),
1541
1600
  analyzersPromise,
1542
1601
  ]);
1602
+ if (extracted.analysisRootError) {
1603
+ return {
1604
+ content: [{ type: "text", text: extracted.analysisRootError }],
1605
+ isError: true,
1606
+ details: {
1607
+ mode: "full",
1608
+ analysisRootError: extracted.analysisRootError,
1609
+ analysisRootValidation: extracted.analysisRootValidation,
1610
+ },
1611
+ };
1612
+ }
1543
1613
  const aborted = signal?.aborted ?? false;
1544
1614
  // #1640: before ANY consumer sees them — the footer reconcile, the widget
1545
1615
  // merge, the rendered counts — demote TypeScript errors on files tsserver
@@ -1662,6 +1732,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1662
1732
  // here; a second list of "which ids don't count" would be the mirror this
1663
1733
  // repo's single-source-of-truth rule forbids.
1664
1734
  const authoritativeRunnerIds = new Set(extracted.analyzed ?? []);
1735
+ const authoritativeRunnerCoverage = extracted.authoritativeCoverage ?? [];
1665
1736
  const foldedProjectSnapshot = foldExtraDiagnosticsIntoSnapshot(scannedSnapshot, extracted.diagnostics.filter((d) => includeFile(d.filePath)), extracted.runners, cwd);
1666
1737
  const projectSnapshot = applyProjectRulePolicy(foldedProjectSnapshot, policyMap);
1667
1738
  const projectDelta = applyProjectRulePolicy(filterProjectDiagnosticsDeltaReport(loadProjectDiagnosticsDeltaReport(cwd), includeFile), policyMap);
@@ -1691,10 +1762,18 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1691
1762
  // LSP sibling above — a retirement nobody can see is how a regression
1692
1763
  // deletes findings silently. Bounded by construction: at most one row per
1693
1764
  // mode=full call, and only when rows were actually retired.
1765
+ const retiredRunnerCounts = new Map();
1694
1766
  const runnerRetiredRows = getFileDiagnosticSummaries()
1695
1767
  .filter((summary) => includeFile(summary.filePath))
1696
1768
  .reduce((total, summary) => total +
1697
- (summary.diagnostics ?? []).filter((diagnostic) => authoritativeRunnerIds.has(runnerIdOf(diagnostic))).length, 0);
1769
+ (summary.diagnostics ?? []).filter((diagnostic) => {
1770
+ const retired = runnerRetirementDecision(diagnostic, summary.filePath, authoritativeRunnerIds, authoritativeRunnerCoverage) === "retire";
1771
+ if (retired) {
1772
+ const runnerId = runnerIdOf(diagnostic);
1773
+ retiredRunnerCounts.set(runnerId, (retiredRunnerCounts.get(runnerId) ?? 0) + 1);
1774
+ }
1775
+ return retired;
1776
+ }).length, 0);
1698
1777
  if (runnerRetiredRows > 0) {
1699
1778
  logLatency({
1700
1779
  type: "phase",
@@ -1703,11 +1782,31 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1703
1782
  durationMs: 0,
1704
1783
  metadata: {
1705
1784
  rows: runnerRetiredRows,
1706
- runners: [...authoritativeRunnerIds].join(","),
1785
+ runners: [...retiredRunnerCounts.keys()].join(","),
1786
+ coverage: authoritativeRunnerCoverage.map((entry) => ({
1787
+ runnerId: entry.runnerId,
1788
+ root: entry.root,
1789
+ files: entry.files.size,
1790
+ })),
1791
+ },
1792
+ });
1793
+ }
1794
+ for (const entry of authoritativeRunnerCoverage) {
1795
+ if (!claimPhaseOncePerSession("runner_coverage_retired", entry.runnerId)) {
1796
+ continue;
1797
+ }
1798
+ logLatency({
1799
+ type: "phase",
1800
+ phase: "runner_coverage_retired",
1801
+ filePath: "",
1802
+ durationMs: 0,
1803
+ metadata: {
1804
+ runnerId: entry.runnerId,
1805
+ count: retiredRunnerCounts.get(entry.runnerId) ?? 0,
1707
1806
  },
1708
1807
  });
1709
1808
  }
1710
- let summaries = await applyInlineSuppressionsToSummaries(mergeDiagnosticsWithWidgetSummaries(getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)), confirmedLspResults, projectSnapshot, projectDelta, authoritativeLspFiles, authoritativeRunnerIds), cwd, policyMap);
1809
+ let summaries = await applyInlineSuppressionsToSummaries(mergeDiagnosticsWithWidgetSummaries(getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)), confirmedLspResults, projectSnapshot, projectDelta, authoritativeLspFiles, authoritativeRunnerIds, authoritativeRunnerCoverage), cwd, policyMap);
1711
1810
  if (unreconciledFiles.size > 0) {
1712
1811
  summaries = summaries.map((summary) => unreconciledFiles.has(path.resolve(summary.filePath))
1713
1812
  ? summarizeDiagnostics(summary.filePath, markUnreconciledFindings(summary.diagnostics), summary.hasFinalSnapshot)
@@ -1831,6 +1930,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1831
1930
  // isn't (a re-run may well complete for that analyzer).
1832
1931
  const abortedIds = new Set(extracted.abortedIds ?? []);
1833
1932
  const genuinelyColdIds = extracted.cold.filter((id) => !abortedIds.has(id));
1933
+ const partialIds = extracted.partial ?? [];
1834
1934
  // #747: an unsafe analysis root (cwd at/above $HOME) skips ALL heavyweight
1835
1935
  // analyzers before anything spawns — rendering that as the per-analyzer
1836
1936
  // "not applicable / unavailable" list would send the caller chasing seven
@@ -1842,7 +1942,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1842
1942
  // shape). Single formatter (extractors.ts) so this note's wording can't
1843
1943
  // drift from any other caller that renders the same `cold` list.
1844
1944
  // #1623 fix-round F5: the "not requested" (quick-mode) batch shares ONE
1845
- // reason (`NOT_REQUESTED_REASON`) across every id — `formatNotRunEntry`
1945
+ // reason (`notRequestedReason`) across every id — `formatNotRunEntry`
1846
1946
  // repeating that same ~130-char sentence per id makes the note nearly
1847
1947
  // unreadable, and the "not applicable / unavailable this run" header
1848
1948
  // below is a dishonest label for it: these lanes ARE applicable and
@@ -1852,14 +1952,21 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1852
1952
  // id's reason really does differ (not a git repo vs binary unavailable
1853
1953
  // vs retry cooldown, ...).
1854
1954
  const coldNote = extracted.unsafeRoot
1855
- ? `\n\nheavyweight analyzers skipped: the working directory resolves at or above the home directory, so a fresh knip/jscpd/madge/gitleaks/govulncheck/trivy/dead-code scan would walk every unrelated tree under it. Re-run from inside a project directory. Absence of their findings is NOT a clean verdict.`
1856
- : !projectRunnersRequested && genuinelyColdIds.length > 0
1857
- ? `\n\nnot run this call (quick mode): ${genuinelyColdIds.join(", ")}. ${NOT_REQUESTED_REASON}. Absence of their findings is NOT a clean verdict.`
1858
- : genuinelyColdIds.length > 0
1859
- ? `\n\ncold (not applicable / unavailable this run): ${genuinelyColdIds
1860
- .map((id) => formatNotRunEntry(id, extracted.coldReasons))
1861
- .join(", ")}. These analyzers have not contributed to this result — absence of their findings is NOT a clean verdict.`
1862
- : "";
1955
+ ? `\n\nheavyweight analyzers skipped: the analysis root resolves at or above the home directory, so a fresh knip/jscpd/madge/gitleaks/govulncheck/trivy/dead-code scan would walk every unrelated tree under it. Supply a project directory below the home ceiling. Absence of their findings is NOT a clean verdict.`
1956
+ : extracted.analysisRootError
1957
+ ? `\n\nheavyweight analyzers skipped: ${extracted.analysisRootError}. Supply an existing project directory below the home ceiling. Absence of their findings is NOT a clean verdict.`
1958
+ : !projectRunnersRequested && genuinelyColdIds.length > 0
1959
+ ? `\n\nnot run this call (quick mode): ${genuinelyColdIds.join(", ")}. ${notRequestedReason(host)}. Absence of their findings is NOT a clean verdict.`
1960
+ : genuinelyColdIds.length > 0
1961
+ ? `\n\ncold (not applicable / unavailable this run): ${genuinelyColdIds
1962
+ .map((id) => formatNotRunEntry(id, extracted.coldReasons))
1963
+ .join(", ")}. These analyzers have not contributed to this result — absence of their findings is NOT a clean verdict.`
1964
+ : "";
1965
+ const partialNote = partialIds.length > 0
1966
+ ? `\n\n⚠ partial coverage (findings included): ${partialIds
1967
+ .map((id) => `${id} — ${extracted.partialReasons?.[id] ?? "coverage is incomplete"}`)
1968
+ .join(", ")}. Coverage is incomplete, so absence of findings is NOT a clean verdict.`
1969
+ : "";
1863
1970
  // #1004: unlike every other analyzer above (knip/jscpd/madge/gitleaks/
1864
1971
  // govulncheck/opengrep/trivy/dead-code all run a FRESH whole-project scan
1865
1972
  // per the fresh-fetch.ts header, so "clean" there really does mean "the
@@ -1923,7 +2030,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1923
2030
  // #1107 phase 2: same "reached the seam, nothing rendered it" gap as #784
1924
2031
  // above, for the generated-name/dir skip counters.
1925
2032
  const generatedSkipNoticeText = projectSnapshot
1926
- ? generatedSkipNotice(projectSnapshot)
2033
+ ? generatedSkipNotice(projectSnapshot, host)
1927
2034
  : undefined;
1928
2035
  const generatedSkipNote = generatedSkipNoticeText
1929
2036
  ? `\n\n${generatedSkipNoticeText}`
@@ -1944,7 +2051,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1944
2051
  ? Date.parse(rawProjectSnapshot.scannedAt)
1945
2052
  : undefined;
1946
2053
  const cheapScanStatusNote = !projectRunnersRequested
1947
- ? `\n\ncheap project scan (tree-sitter/fact-rules/ast-grep): not run this call (${NOT_REQUESTED_REASON}).`
2054
+ ? `\n\ncheap project scan (tree-sitter/fact-rules/ast-grep): not run this call (${notRequestedReason(host)}).`
1948
2055
  : options.refreshRunners === "cached"
1949
2056
  ? cheapScanScannedAtMs !== undefined &&
1950
2057
  Number.isFinite(cheapScanScannedAtMs)
@@ -1989,6 +2096,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1989
2096
  details: {
1990
2097
  ...result.details,
1991
2098
  coldRunners: extracted.cold,
2099
+ partialRunners: partialIds,
1992
2100
  // #1623: the specific reason each cold id was skipped (single source
1993
2101
  // of truth: extractors.ts's `formatNotRunEntry` renders the same map
1994
2102
  // into the text note above) — lets a caller check WHY without parsing
@@ -2007,7 +2115,11 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
2007
2115
  // #747: true when the fresh fetch refused an at-or-above-$HOME root —
2008
2116
  // lets a caller distinguish "skipped for safety" from per-analyzer
2009
2117
  // cold reasons without parsing the text note.
2010
- analyzersUnsafeRoot: extracted.unsafeRoot ?? false,
2118
+ // This is the fetch seam's explicit-root policy. The cwd walk below is
2119
+ // intentionally separate: it answers a different root question.
2120
+ analyzersUnsafeRoot: extracted.analysisRootValidation?.state === "unsafe" ||
2121
+ extracted.unsafeRoot === true,
2122
+ analysisRootValidation: extracted.analysisRootValidation,
2011
2123
  // #747: true when the cwd resolved at/above $HOME so the cheap project
2012
2124
  // scan and the LSP workspace sweep both refused to walk — lets a caller
2013
2125
  // distinguish "walked nothing for safety" from a genuinely clean sweep.
@@ -2067,6 +2179,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
2067
2179
  unconfirmedLspNote +
2068
2180
  auxiliaryCoverageNote +
2069
2181
  lspPrimaryVsAuxiliaryNote +
2182
+ partialNote +
2070
2183
  coldNote +
2071
2184
  testRunnerEditScopedNote +
2072
2185
  failedNote +
@@ -2086,6 +2199,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
2086
2199
  }
2087
2200
  if (missingNote ||
2088
2201
  coldNote ||
2202
+ partialNote ||
2089
2203
  testRunnerEditScopedNote ||
2090
2204
  failedNote ||
2091
2205
  dispositionSuppressedNote ||
@@ -2107,6 +2221,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
2107
2221
  unconfirmedLspNote +
2108
2222
  auxiliaryCoverageNote +
2109
2223
  lspPrimaryVsAuxiliaryNote +
2224
+ partialNote +
2110
2225
  coldNote +
2111
2226
  testRunnerEditScopedNote +
2112
2227
  failedNote +