@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
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Session-scoped cooldown for commands whose spawn TIMED OUT (#1995).
3
+ *
4
+ * Live evidence: one wedged `markdownlint-cli2.cmd` on Windows charged its
5
+ * failure budget three times for a single edit — availability verification
6
+ * (30s, SIGTERM), autofix `--fix` (30s), and the lint runner (15s) each paid
7
+ * separately, because a positive probe/cache verdict said nothing about the
8
+ * command's ability to COMPLETE. Total post-edit cost: 52-60 seconds.
9
+ *
10
+ * This seam is the shared negative evidence:
11
+ * - `noteSpawnTimeout` records that a resolved command timed out, in which
12
+ * phase, and what wrapper kind it had; every record emits one bounded
13
+ * latency row so the session stays auditable.
14
+ * - `isInSpawnTimeoutCooldown` is consulted by every invocation path for that
15
+ * command — verification, autofix, and lint — so ONE wedged executable
16
+ * consumes at most ONE bounded failure budget per edit (invariant 1) and a
17
+ * timeout/skipped result is never re-reported as clean (invariant 4).
18
+ *
19
+ * Durability contract: SESSION. A hot loop of edits must not retry (a wedged
20
+ * `.cmd` shim does not heal between edits), but a new session may — the
21
+ * executable or its environment may have changed. Reset is registered in the
22
+ * session-state registry (`spawn-timeout-cooldown:latches`) and wired into
23
+ * `handleSessionStart`.
24
+ */
25
+ import path from "node:path";
26
+ import { logLatency } from "./latency-logger.js";
27
+ const COOLDOWN_STATE_KEY = Symbol.for("pi-lens:spawn-timeout-cooldown");
28
+ const _global = globalThis;
29
+ if (!_global[COOLDOWN_STATE_KEY]) {
30
+ _global[COOLDOWN_STATE_KEY] = { timedOutByCommand: new Map() };
31
+ }
32
+ const timedOutByCommand = _global[COOLDOWN_STATE_KEY].timedOutByCommand;
33
+ /** Wrapper kind for the telemetry record: how the command will be launched. */
34
+ function wrapperKindOf(command) {
35
+ const ext = path.extname(command);
36
+ return ext ? ext.slice(1) : "bare";
37
+ }
38
+ /**
39
+ * Cooldown key: the command's basename minus extension, lowercased.
40
+ *
41
+ * Deliberately NOT the full resolved path: the three lanes resolve the same
42
+ * physical binary through different helpers (PATH-resolved absolute,
43
+ * `<cwd>/node_modules/.bin/...`, bare name), and cross-lane sharing is the
44
+ * entire point (#1995 - otherwise each lane pays its own first budget).
45
+ */
46
+ function cooldownKey(command) {
47
+ return path
48
+ .basename(command)
49
+ .replace(/\.[^.]+$/, "")
50
+ .toLowerCase();
51
+ }
52
+ export function noteSpawnTimeout(input) {
53
+ const key = cooldownKey(input.command);
54
+ timedOutByCommand.set(key, {
55
+ tool: input.tool,
56
+ command: input.command,
57
+ phase: input.phase,
58
+ atMs: Date.now(),
59
+ });
60
+ logLatency({
61
+ type: "phase",
62
+ toolName: input.tool,
63
+ phase: "spawn_timeout_cooldown",
64
+ filePath: input.command,
65
+ durationMs: input.durationMs ?? 0,
66
+ status: "cooldown_armed",
67
+ metadata: {
68
+ command: input.command,
69
+ wrapperKind: wrapperKindOf(input.command),
70
+ timeoutPhase: input.phase,
71
+ ...(input.durationMs !== undefined && {
72
+ timeoutBudgetMs: input.durationMs,
73
+ }),
74
+ ...(input.teardown && {
75
+ teardownMs: input.teardown.ms,
76
+ teardownOutcome: input.teardown.outcome,
77
+ }),
78
+ },
79
+ });
80
+ }
81
+ /**
82
+ * True while `command` is cooling down after a spawn timeout. Every
83
+ * invocation path for this command should skip WITHOUT spawning and report
84
+ * an honest "not checked" outcome (skipped / 0-fixes), never clean.
85
+ */
86
+ export function isInSpawnTimeoutCooldown(command) {
87
+ return timedOutByCommand.has(cooldownKey(command));
88
+ }
89
+ /**
90
+ * Session-start re-arm seam (registered in the session-state registry):
91
+ * a new session may retry a command the previous session cooled down -
92
+ * the executable or its environment may have changed.
93
+ */
94
+ export function resetSpawnTimeoutCooldowns() {
95
+ timedOutByCommand.clear();
96
+ }
@@ -240,7 +240,10 @@ export function resolveStartupScanContext(cwd, options = {}) {
240
240
  const cached = startupScanContextCache.get(cacheKey);
241
241
  if (cached)
242
242
  return cached;
243
- const result = { ...computeStartupScanContext(cwd, options), computedAt: Date.now() };
243
+ const result = {
244
+ ...computeStartupScanContext(cwd, options),
245
+ computedAt: Date.now(),
246
+ };
244
247
  startupScanContextCache.set(cacheKey, result);
245
248
  return result;
246
249
  }
@@ -0,0 +1,7 @@
1
+ export function normalizeToolDefinition(tool) {
2
+ const name = typeof tool.name === "string" ? tool.name.trim() : "tool";
3
+ const description = typeof tool.description === "string" && tool.description.trim().length > 0
4
+ ? tool.description
5
+ : `Use the ${name} tool.`;
6
+ return { ...tool, description };
7
+ }
@@ -671,16 +671,29 @@ const FORMATTER_POLICY_BY_EXTENSION = new Map([
671
671
  // imports and spreads this same Set (#1134; previously two parallel hand-maintained
672
672
  // lists, the #883 single-source-of-truth class).
673
673
  export const OXFMT_SUPPORTED_EXTENSIONS = new Set([
674
- ".js", ".jsx", ".mjs", ".cjs",
675
- ".ts", ".tsx", ".mts", ".cts",
674
+ ".js",
675
+ ".jsx",
676
+ ".mjs",
677
+ ".cjs",
678
+ ".ts",
679
+ ".tsx",
680
+ ".mts",
681
+ ".cts",
676
682
  ".vue",
677
683
  ".svelte",
678
- ".css", ".scss", ".less",
679
- ".html", ".htm",
680
- ".json", ".jsonc",
681
- ".yaml", ".yml",
682
- ".md", ".mdx",
683
- ".graphql", ".gql",
684
+ ".css",
685
+ ".scss",
686
+ ".less",
687
+ ".html",
688
+ ".htm",
689
+ ".json",
690
+ ".jsonc",
691
+ ".yaml",
692
+ ".yml",
693
+ ".md",
694
+ ".mdx",
695
+ ".graphql",
696
+ ".gql",
684
697
  ".toml",
685
698
  ]);
686
699
  // Add .vue entry (no prior formatter policy existed for this extension)
@@ -707,7 +720,8 @@ FORMATTER_POLICY_BY_EXTENSION.set(".svelte", {
707
720
  gate: "config-first",
708
721
  });
709
722
  for (const [ext, policy] of FORMATTER_POLICY_BY_EXTENSION) {
710
- if (OXFMT_SUPPORTED_EXTENSIONS.has(ext) && !policy.formatterNames.includes("oxfmt")) {
723
+ if (OXFMT_SUPPORTED_EXTENSIONS.has(ext) &&
724
+ !policy.formatterNames.includes("oxfmt")) {
711
725
  policy.formatterNames.push("oxfmt");
712
726
  }
713
727
  }
@@ -2044,7 +2058,8 @@ export function biomeConfigArgs(cwd) {
2044
2058
  if (getBiomeConfigPath(cwd))
2045
2059
  return [];
2046
2060
  return [
2047
- "--config-path=" + resolvePackagePath(import.meta.url, "config/biome/core.jsonc"),
2061
+ "--config-path=" +
2062
+ resolvePackagePath(import.meta.url, "config/biome/core.jsonc"),
2048
2063
  ];
2049
2064
  }
2050
2065
  export function hasGolangciConfig(cwd) {
@@ -2150,7 +2165,7 @@ export function hasOrmoluConfig(cwd) {
2150
2165
  return findNearestContaining(cwd, [".ormolu"]) !== undefined;
2151
2166
  }
2152
2167
  export function hasTaploConfig(cwd) {
2153
- return findNearestContaining(cwd, ["taplo.toml", ".taplo.toml"]) !== undefined;
2168
+ return (findNearestContaining(cwd, ["taplo.toml", ".taplo.toml"]) !== undefined);
2154
2169
  }
2155
2170
  // `terraform fmt` itself is deliberately unconfigurable (no rc file, no
2156
2171
  // per-project options — HashiCorp's own docs call this out). The nearest
@@ -137,7 +137,8 @@ export function wrapToolForCompactLine(tool) {
137
137
  // pi invokes tool renderers with `{ content, details }` -- the failure
138
138
  // bit lives on `context.isError`, not the result (#1341 review). Keep
139
139
  // `result.isError` as a fallback for direct/legacy callers.
140
- const contextIsError = context?.isError;
140
+ const contextIsError = context
141
+ ?.isError;
141
142
  const isError = contextIsError ?? resultLike.isError === true;
142
143
  const line = buildCompactToolLine(summaryText, isError === true, theme);
143
144
  return {
@@ -277,11 +277,15 @@ export class TreeSitterClient {
277
277
  static QUERY_BATCH_CACHE_MAX_ENTRIES = 256;
278
278
  queryCacheCap() {
279
279
  const value = Number.parseInt(process.env.PI_LENS_TREE_SITTER_QUERY_CACHE_CAP ?? "", 10);
280
- return Number.isSafeInteger(value) && value > 0 ? value : TreeSitterClient.QUERY_CACHE_MAX_ENTRIES;
280
+ return Number.isSafeInteger(value) && value > 0
281
+ ? value
282
+ : TreeSitterClient.QUERY_CACHE_MAX_ENTRIES;
281
283
  }
282
284
  queryBatchCacheCap() {
283
285
  const value = Number.parseInt(process.env.PI_LENS_TREE_SITTER_QUERY_BATCH_CACHE_CAP ?? "", 10);
284
- return Number.isSafeInteger(value) && value > 0 ? value : TreeSitterClient.QUERY_BATCH_CACHE_MAX_ENTRIES;
286
+ return Number.isSafeInteger(value) && value > 0
287
+ ? value
288
+ : TreeSitterClient.QUERY_BATCH_CACHE_MAX_ENTRIES;
285
289
  }
286
290
  cacheQuery(key, value) {
287
291
  this.queryCache.delete(key);
@@ -2141,7 +2145,9 @@ export class TreeSitterClient {
2141
2145
  }
2142
2146
  // Ambiguous (shadowed/duplicated), reassigned anywhere, or backed by a
2143
2147
  // non-const binding somewhere in the file: refuse to resolve.
2144
- if (hasNonConstBinding || hasReassignment || constDeclarators.length !== 1) {
2148
+ if (hasNonConstBinding ||
2149
+ hasReassignment ||
2150
+ constDeclarators.length !== 1) {
2145
2151
  return null;
2146
2152
  }
2147
2153
  return constDeclarators[0].childForFieldName?.("value") ?? null;
@@ -2978,7 +2984,7 @@ export class TreeSitterClient {
2978
2984
  const hasExceptionSpec = clauseNode.children.some((c) => {
2979
2985
  if (!c.isNamed)
2980
2986
  return false;
2981
- return (c.type !== "block");
2987
+ return c.type !== "block";
2982
2988
  });
2983
2989
  // Fire ONLY when bare (no exception spec)
2984
2990
  return !hasExceptionSpec;
@@ -50,7 +50,7 @@ export function logTreeSitterCacheStats(options) {
50
50
  totalBytes: options.stats.totalBytes,
51
51
  totalLines: options.stats.totalLines,
52
52
  },
53
- ...(options.astGrep ? { astGrep: options.astGrep } : {}),
53
+ astGrep: options.astGrep,
54
54
  },
55
55
  });
56
56
  }
@@ -72,7 +72,7 @@ export function logTreeSitterDiagnostic(entry) {
72
72
  ...(entry.languageId ? { languageId: entry.languageId } : {}),
73
73
  status: entry.level ?? "error",
74
74
  reason: entry.message,
75
- metadata: { subsystem: entry.subsystem, ...(entry.metadata ?? {}) },
75
+ metadata: { subsystem: entry.subsystem, ...entry.metadata },
76
76
  });
77
77
  }
78
78
  export function getTreeSitterLogPath() {
@@ -914,7 +914,9 @@ export class TreeSitterSymbolExtractor {
914
914
  ...(visibility ? { visibility } : {}),
915
915
  ...(decorators.length > 0 ? { decorators } : {}),
916
916
  ...(isAsync ? { isAsync: true } : {}),
917
- ...(docInfo ? { doc: docInfo.text, docStartLine: docInfo.startLine } : {}),
917
+ ...(docInfo
918
+ ? { doc: docInfo.text, docStartLine: docInfo.startLine }
919
+ : {}),
918
920
  };
919
921
  }
920
922
  // Comment node kinds across grammars that use tree-sitter's conventional
@@ -983,7 +985,8 @@ export class TreeSitterSymbolExtractor {
983
985
  let start = -1; // inclusive start index of the accepted comment run
984
986
  while (cursor >= 0 && isComment(siblings[cursor])) {
985
987
  const candidate = siblings[cursor];
986
- const gapRows = boundaryRow !== undefined && typeof candidate.endPosition?.row === "number"
988
+ const gapRows = boundaryRow !== undefined &&
989
+ typeof candidate.endPosition?.row === "number"
987
990
  ? boundaryRow - candidate.endPosition.row
988
991
  : 0;
989
992
  if (gapRows > 1)
@@ -1081,7 +1084,9 @@ export class TreeSitterSymbolExtractor {
1081
1084
  extractDecorators(node) {
1082
1085
  const isDeco = (n) => !!n && TreeSitterSymbolExtractor.DECORATOR_NODE_KINDS.has(n.type);
1083
1086
  const text = (n) => {
1084
- const first = String(n?.text ?? "").split(/\r?\n/, 1)[0]?.trim() ?? "";
1087
+ const first = String(n?.text ?? "")
1088
+ .split(/\r?\n/, 1)[0]
1089
+ ?.trim() ?? "";
1085
1090
  return first.length > 120 ? `${first.slice(0, 117)}…` : first;
1086
1091
  };
1087
1092
  const out = [];
@@ -1125,7 +1130,8 @@ export class TreeSitterSymbolExtractor {
1125
1130
  refNode = capture.node;
1126
1131
  if (captureName.startsWith("type"))
1127
1132
  referenceKind = "type";
1128
- else if (captureName.startsWith("call") || captureName.startsWith("new")) {
1133
+ else if (captureName.startsWith("call") ||
1134
+ captureName.startsWith("new")) {
1129
1135
  referenceKind = "call";
1130
1136
  }
1131
1137
  }
@@ -1134,7 +1140,8 @@ export class TreeSitterSymbolExtractor {
1134
1140
  refNode = capture.node;
1135
1141
  if (captureName.startsWith("type"))
1136
1142
  referenceKind = "type";
1137
- else if (captureName.startsWith("call") || captureName.startsWith("new")) {
1143
+ else if (captureName.startsWith("call") ||
1144
+ captureName.startsWith("new")) {
1138
1145
  referenceKind = "call";
1139
1146
  }
1140
1147
  }
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as net from "node:net";
3
3
  import * as path from "node:path";
4
4
  import { readInstanceRegistry, } from "./instance-registry.js";
5
- import { realIsPidAlive, STALE_HEARTBEAT_MS, } from "./instance-reaper.js";
5
+ import { realIsPidAlive, STALE_HEARTBEAT_MS } from "./instance-reaper.js";
6
6
  import { logLatency } from "./latency-logger.js";
7
7
  import { touchCoverageGap } from "./lsp/diagnostic-binding.js";
8
8
  import { loadLspService } from "./lsp-lazy.js";
@@ -42,7 +42,9 @@ async function serveRequest(req) {
42
42
  if (Date.now() > req.deadlineAt) {
43
43
  throw new Error("deadline exceeded");
44
44
  }
45
- return (await loadLspService()).getLSPService().codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
45
+ return (await loadLspService())
46
+ .getLSPService()
47
+ .codeAction(req.file, range.start.line, range.start.character, range.end.line, range.end.character);
46
48
  }));
47
49
  const servedAt = Date.now();
48
50
  if (servedAt > req.deadlineAt)
@@ -65,10 +67,13 @@ async function serveRequest(req) {
65
67
  req.version !== WARM_DIAGNOSTICS_SCHEMA_VERSION) {
66
68
  return { error: "schema mismatch" };
67
69
  }
68
- if (Date.now() > req.deadlineAt || contentHash(req.content) !== req.contentHash) {
70
+ if (Date.now() > req.deadlineAt ||
71
+ contentHash(req.content) !== req.contentHash) {
69
72
  return { error: "stale request" };
70
73
  }
71
- const touched = await (await loadLspService()).getLSPService().touchFile(req.file, req.content, {
74
+ const touched = await (await loadLspService())
75
+ .getLSPService()
76
+ .touchFile(req.file, req.content, {
72
77
  diagnostics: "document",
73
78
  collectDiagnostics: true,
74
79
  clientScope: "with-auxiliary",
@@ -82,7 +87,9 @@ async function serveRequest(req) {
82
87
  // either test passes — which is exactly the coincidence `touchCoverageGap`'s
83
88
  // own doc comment warns against. One reader, one rule.
84
89
  const coverageGap = touchCoverageGap(touched);
85
- if (servedAt <= req.deadlineAt && touched !== undefined && !touched.inconclusive) {
90
+ if (servedAt <= req.deadlineAt &&
91
+ touched !== undefined &&
92
+ !touched.inconclusive) {
86
93
  state.servedDiagnosticHashes.set(normalizeFilePath(req.file), req.contentHash);
87
94
  }
88
95
  return {
@@ -6,7 +6,8 @@ import { visibleWidth } from "./deps/pi-tui.js";
6
6
  import { normalizeEphemeralMapKey, normalizeMapKey } from "./path-utils.js";
7
7
  import { fitLine } from "./tui-fit.js";
8
8
  import { WriteOrderingGuard } from "./write-ordering-guard.js";
9
- import { collectForwardImportMtimes, MTIME_DRIFT_TOLERANCE_MS, } from "./blocker-freshness.js";
9
+ import { collectForwardImportMtimes } from "./blocker-freshness.js";
10
+ import { freshnessFromMtime } from "./freshness.js";
10
11
  import { PAST_EOF_STALE_MARKER } from "./diagnostic-line-freshness.js";
11
12
  import { STALE_LINE_MARKER } from "./stale-marker.js";
12
13
  /**
@@ -89,8 +90,7 @@ function pruneInactiveFileRecords(now = Date.now()) {
89
90
  if (files.size <= MAX_INACTIVE_FILE_RECORDS)
90
91
  return;
91
92
  const victims = [...files.entries()]
92
- .filter(([, rec]) => now - rec.touchedAt > ACTIVE_FILE_IDLE_MS &&
93
- !hasLiveDiagnostic(rec))
93
+ .filter(([, rec]) => now - rec.touchedAt > ACTIVE_FILE_IDLE_MS && !hasLiveDiagnostic(rec))
94
94
  .sort(([, a], [, b]) => a.touchedAt - b.touchedAt);
95
95
  for (const [key] of victims) {
96
96
  if (files.size <= MAX_INACTIVE_FILE_RECORDS)
@@ -395,7 +395,8 @@ function countDiagnostics(diags) {
395
395
  // A dependency-drift demotion (#1631 criterion 3) is different: the
396
396
  // finding itself is still real evidence, only its BLOCKING authority is
397
397
  // revoked until re-confirmed, so it stays in the error/warning tally.
398
- if (diagnostic.stale && (diagnostic.staleReason ?? "past-eof") === "past-eof")
398
+ if (diagnostic.stale &&
399
+ (diagnostic.staleReason ?? "past-eof") === "past-eof")
399
400
  continue;
400
401
  if (diagnostic.severity === "error")
401
402
  errors++;
@@ -457,7 +458,8 @@ function applyPastEofGate(rec, lineCountCache) {
457
458
  function freshestObservation(diags, fallback) {
458
459
  let newest;
459
460
  for (const d of diags) {
460
- if (d.observedAt != null && (newest === undefined || d.observedAt > newest)) {
461
+ if (d.observedAt != null &&
462
+ (newest === undefined || d.observedAt > newest)) {
461
463
  newest = d.observedAt;
462
464
  }
463
465
  }
@@ -473,7 +475,7 @@ function freshestObservation(diags, fallback) {
473
475
  * errors-only LSP re-check is entitled to replace.
474
476
  */
475
477
  function isLspErrorEntry(d) {
476
- return d.tool === "lsp" && (d.semantic === "blocking" || d.severity === "error");
478
+ return (d.tool === "lsp" && (d.semantic === "blocking" || d.severity === "error"));
477
479
  }
478
480
  /**
479
481
  * Reconcile a CONFIRMED cascade neighbor re-check (#1093) into the footer,
@@ -614,7 +616,8 @@ export async function reconcileStaleWidgetFiles() {
614
616
  // under this gate, not from cross-test state. Same tolerance, same
615
617
  // constant, for the same reason.
616
618
  if (rec.allDiagnostics.length === 0) {
617
- return mtimeMs > rec.touchedAt + MTIME_DRIFT_TOLERANCE_MS
619
+ return freshnessFromMtime({ mtimeMs, referenceMs: rec.touchedAt })
620
+ .verdict === "stale"
618
621
  ? { mapKey, action: "drop" }
619
622
  : { mapKey, action: "keep" };
620
623
  }
@@ -625,7 +628,13 @@ export async function reconcileStaleWidgetFiles() {
625
628
  // at dispatch/integration.ts). A missing per-entry stamp (a migrated
626
629
  // pre-#1186 record) inherits the record's `touchedAt`. Tolerance matches
627
630
  // the Windows host-clock skew rationale above.
628
- const survivors = rec.allDiagnostics.filter((d) => !(mtimeMs > (d.observedAt ?? rec.touchedAt) + MTIME_DRIFT_TOLERANCE_MS));
631
+ const survivors = rec.allDiagnostics.filter((d) => {
632
+ const v = freshnessFromMtime({
633
+ mtimeMs,
634
+ referenceMs: d.observedAt ?? rec.touchedAt,
635
+ });
636
+ return v.verdict !== "stale";
637
+ });
629
638
  if (survivors.length === rec.allDiagnostics.length) {
630
639
  return { mapKey, action: "keep" }; // nothing stale
631
640
  }
@@ -695,7 +704,10 @@ export async function reconcileStaleWidgetDependencyBlockers(cwd, turnIndex) {
695
704
  // across 200 writes; #1491/#1498 precedent for the same host-clock skew).
696
705
  // +1ms produced 42 false demotions in 50 runs on Windows; +50ms clears the
697
706
  // measured skew while staying far below the gap between real edits.
698
- if (importMtimes.some((im) => im.mtimeMs > baseline + MTIME_DRIFT_TOLERANCE_MS)) {
707
+ if (importMtimes.some((im) => freshnessFromMtime({
708
+ mtimeMs: im.mtimeMs,
709
+ referenceMs: baseline,
710
+ }).verdict === "stale")) {
699
711
  d.stale = true;
700
712
  d.staleReason = "dependency-drift";
701
713
  changed = true;
@@ -1055,7 +1067,9 @@ function formatFileRowVertical(rec, theme) {
1055
1067
  const formatMark = (failedFormatters.length > 0
1056
1068
  ? red(` fmt-failed:${failedFormatters.join(",")}`)
1057
1069
  : "") +
1058
- (changedFormatters.length > 0 ? dim(` fmt:${changedFormatters.join(",")}`) : "");
1070
+ (changedFormatters.length > 0
1071
+ ? dim(` fmt:${changedFormatters.join(",")}`)
1072
+ : "");
1059
1073
  return ` ${dot} ${base} ${dim(runnerNames)}${formatMark}${counts}`;
1060
1074
  }
1061
1075
  function packHorizontalRow(recs, totalWidth, theme) {
@@ -1194,7 +1208,9 @@ function hasFailedFormatter(rec) {
1194
1208
  return [...rec.formatters.values()].some((f) => !f.success);
1195
1209
  }
1196
1210
  function shouldRenderFile(rec) {
1197
- return rec.hasFinalDiagnosticsSnapshot || hasChangedFormatter(rec) || hasFailedFormatter(rec);
1211
+ return (rec.hasFinalDiagnosticsSnapshot ||
1212
+ hasChangedFormatter(rec) ||
1213
+ hasFailedFormatter(rec));
1198
1214
  }
1199
1215
  function hasLiveDiagnostic(rec) {
1200
1216
  return rec.hasFinalDiagnosticsSnapshot && rec.diagnostics.length > 0;
@@ -885,7 +885,9 @@ function resolveLangExtensions(value) {
885
885
  const kind = value.toLowerCase();
886
886
  const extensions = KIND_EXTENSIONS[kind];
887
887
  if (!extensions) {
888
- const known = Object.keys(KIND_EXTENSIONS).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(", ");
888
+ const known = Object.keys(KIND_EXTENSIONS)
889
+ .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
890
+ .join(", ");
889
891
  throw new WordIndexQueryError(`Unknown lang: "${value}" in word-index query — supported languages: ${known}.`);
890
892
  }
891
893
  return extensions;
@@ -52,7 +52,9 @@ const TOPOLOGY_MAX_WALK_ENTRIES = 512;
52
52
  const TOPOLOGY_IDLE_EVICT_MS_DEFAULT = 20 * 60_000;
53
53
  function topologyIdleEvictMs() {
54
54
  const value = Number.parseInt(process.env.PI_LENS_WORKSPACE_TOPOLOGY_IDLE_EVICT_MS ?? "", 10);
55
- return Number.isSafeInteger(value) && value > 0 ? value : TOPOLOGY_IDLE_EVICT_MS_DEFAULT;
55
+ return Number.isSafeInteger(value) && value > 0
56
+ ? value
57
+ : TOPOLOGY_IDLE_EVICT_MS_DEFAULT;
56
58
  }
57
59
  function deleteDirMarker(key) {
58
60
  const entry = dirMarkerCache.get(key);
@@ -236,7 +238,11 @@ function walkToNearestMatch(startDir, cacheSuffix, matches, capMetadata, homeDir
236
238
  }
237
239
  depth += 1;
238
240
  }
239
- const entry = { dir: found, dirMtimes, lastUsedAt: Date.now() };
241
+ const entry = {
242
+ dir: found,
243
+ dirMtimes,
244
+ lastUsedAt: Date.now(),
245
+ };
240
246
  walkCache.set(key, entry);
241
247
  touchWalk(key, entry);
242
248
  while (walkCache.size > TOPOLOGY_MAX_WALK_ENTRIES) {
@@ -94,6 +94,14 @@ export function resetZizmorTokenAvailability() {
94
94
  ghTokenLatch.reset();
95
95
  cachedToken = undefined;
96
96
  }
97
+ /**
98
+ * Test-only internals access for the session-state registry probe (#1535):
99
+ * the conformance suite arms a latched "missing" verdict and proves the
100
+ * session reset forgets it.
101
+ */
102
+ export function _getZizmorTokenLatchForTests() {
103
+ return ghTokenLatch;
104
+ }
97
105
  /** Test-only alias — kept so existing tests don't need a rename. */
98
106
  export function _resetZizmorTokenCacheForTests() {
99
107
  resetZizmorTokenAvailability();
@@ -185,7 +193,7 @@ async function deriveGhCliToken() {
185
193
  * and logs the decision. Centralized so the empty-answer and failure paths
186
194
  * can't drift on which fields get set.
187
195
  */
188
- function recordGhTokenUnavailable({ outcome, cause }, elapsedMs, hostStallMs) {
196
+ function recordGhTokenUnavailable({ outcome, cause, }, elapsedMs, hostStallMs) {
189
197
  const retryAfterMs = ghTokenLatch.noteUnavailable(outcome, cause);
190
198
  if (outcome === "transient") {
191
199
  recordZizmorOfflineDegradation(`gh auth token probe ${cause}; running offline until the next zizmor start (retry allowed in ${Math.round(retryAfterMs / 1000)}s)`);
@@ -41,21 +41,29 @@ const translations = {
41
41
  };
42
42
  let currentLocale = "en";
43
43
  export function initI18n(pi) {
44
- pi.events?.emit?.("pi-core/i18n/registerBundle", { namespace: "pi-lens", defaultLocale: "en", locales: translations });
44
+ pi.events?.emit?.("pi-core/i18n/registerBundle", {
45
+ namespace: "pi-lens",
46
+ defaultLocale: "en",
47
+ locales: translations,
48
+ });
45
49
  pi.events?.emit?.("pi-core/i18n/requestApi", {
46
50
  onReady: (api) => {
47
51
  const next = api.getLocale?.();
48
52
  if (isLocale(next))
49
53
  currentLocale = next;
50
- api.onLocaleChange?.((locale) => { if (isLocale(locale))
51
- currentLocale = locale; });
54
+ api.onLocaleChange?.((locale) => {
55
+ if (isLocale(locale))
56
+ currentLocale = locale;
57
+ });
52
58
  },
53
59
  });
54
60
  }
55
61
  export function t(key, fallback, params = {}) {
56
- const template = currentLocale === "en" ? fallback : translations[currentLocale]?.[key] ?? fallback;
62
+ const template = currentLocale === "en"
63
+ ? fallback
64
+ : (translations[currentLocale]?.[key] ?? fallback);
57
65
  return template.replaceAll(/\{(\w+)\}/g, (_, name) => String(params[name] ?? `{${name}}`));
58
66
  }
59
67
  function isLocale(locale) {
60
- return locale === "en" || locale === "es" || locale === "fr" || locale === "pt-BR";
68
+ return (locale === "en" || locale === "es" || locale === "fr" || locale === "pt-BR");
61
69
  }