@herbertgao/pi-extensions 2026.10.1 → 2026.10.2

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 (707) hide show
  1. package/README.md +13 -9
  2. package/THIRD_PARTY_NOTICES.md +2 -2
  3. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +2 -2
  4. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +2 -2
  5. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +1 -1
  6. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +1 -1
  7. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +2 -2
  8. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +1 -1
  9. package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +21 -21
  10. package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
  11. package/node_modules/@dietrichgebert/ponytail/AGENTS.md +21 -21
  12. package/node_modules/@dietrichgebert/ponytail/README.md +68 -72
  13. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +7 -0
  14. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +30 -30
  15. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-map.js +103 -0
  16. package/node_modules/@dietrichgebert/ponytail/package.json +2 -2
  17. package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +33 -101
  18. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +89 -32
  19. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +13 -12
  20. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +17 -16
  21. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +9 -10
  22. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +96 -57
  23. package/node_modules/@herbertgao/pi-agency/LICENSE +21 -0
  24. package/node_modules/@herbertgao/pi-agency/README.md +40 -0
  25. package/node_modules/@herbertgao/pi-agency/package.json +53 -0
  26. package/node_modules/@herbertgao/pi-agency/src/index.ts +441 -0
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +12 -12
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +30 -6
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +15 -9
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +27 -9
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +4 -1
  32. package/node_modules/@herbertgao/pi-cc-extensions/package.json +2 -2
  33. package/node_modules/@narumitw/pi-caffeinate/package.json +3 -3
  34. package/node_modules/@tifan/pi-mermaid-open/package.json +5 -1
  35. package/node_modules/@tifan/pi-mermaid-open/src/index.ts +26 -9
  36. package/node_modules/@tifan/pi-recap/package.json +1 -1
  37. package/node_modules/@tifan/pi-recap/src/index.ts +104 -20
  38. package/node_modules/@tifan/pi-recap/src/models.ts +46 -4
  39. package/node_modules/pi-antigravity/README.md +23 -2
  40. package/node_modules/pi-antigravity/package.json +5 -3
  41. package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +3 -2
  42. package/node_modules/pi-antigravity/src/features/generate-image.ts +72 -0
  43. package/node_modules/pi-antigravity/src/features/google-search.ts +71 -0
  44. package/node_modules/pi-antigravity/src/image/image.ts +86 -47
  45. package/node_modules/pi-antigravity/src/image/native.ts +69 -0
  46. package/node_modules/pi-antigravity/src/index.ts +52 -137
  47. package/node_modules/pi-antigravity/src/search/search.ts +130 -31
  48. package/node_modules/pi-antigravity/src/stream/stream.ts +162 -113
  49. package/node_modules/pi-antigravity/src/types/enums.ts +1 -0
  50. package/node_modules/pi-antigravity/src/types/types.ts +1 -1
  51. package/node_modules/pi-antigravity/src/utils/security.ts +47 -1
  52. package/node_modules/pi-antigravity/src/utils/util.ts +38 -6
  53. package/node_modules/pi-lens/CHANGELOG.md +1064 -0
  54. package/node_modules/pi-lens/README.md +115 -25
  55. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +6 -2
  56. package/node_modules/pi-lens/dist/chunk-22AVIGXS.js +560 -0
  57. package/node_modules/pi-lens/dist/chunk-27BBHSZC.js +106 -0
  58. package/node_modules/pi-lens/dist/chunk-2BEMIWEW.js +51 -0
  59. package/node_modules/pi-lens/dist/chunk-2EECBNC5.js +89 -0
  60. package/node_modules/pi-lens/dist/chunk-34U7PLGE.js +23 -0
  61. package/node_modules/pi-lens/dist/chunk-3I5QFT3N.js +181 -0
  62. package/node_modules/pi-lens/dist/chunk-3MED75HT.js +37 -0
  63. package/node_modules/pi-lens/dist/chunk-47D2BO4S.js +87 -0
  64. package/node_modules/pi-lens/dist/chunk-4RERDEXR.js +348 -0
  65. package/node_modules/pi-lens/dist/chunk-4W2PLC4J.js +27 -0
  66. package/node_modules/pi-lens/dist/chunk-52H5B5TC.js +202 -0
  67. package/node_modules/pi-lens/dist/chunk-54B42YRX.js +27 -0
  68. package/node_modules/pi-lens/dist/chunk-5RXBNSW2.js +266 -0
  69. package/node_modules/pi-lens/dist/chunk-5THXD6X5.js +201 -0
  70. package/node_modules/pi-lens/dist/chunk-5W3R6LFT.js +24 -0
  71. package/node_modules/pi-lens/dist/chunk-5ZEJHV35.js +341 -0
  72. package/node_modules/pi-lens/dist/chunk-6P62QVEA.js +118 -0
  73. package/node_modules/pi-lens/dist/chunk-6QIUX4EP.js +459 -0
  74. package/node_modules/pi-lens/dist/chunk-6VCD4VKZ.js +78 -0
  75. package/node_modules/pi-lens/dist/chunk-7F72PXY2.js +326 -0
  76. package/node_modules/pi-lens/dist/chunk-7FBF7NPR.js +998 -0
  77. package/node_modules/pi-lens/dist/chunk-7U2IDNXN.js +37 -0
  78. package/node_modules/pi-lens/dist/chunk-ABBOA7UD.js +157 -0
  79. package/node_modules/pi-lens/dist/chunk-AHDW3GPE.js +50 -0
  80. package/node_modules/pi-lens/dist/chunk-AJ3QXTRQ.js +756 -0
  81. package/node_modules/pi-lens/dist/chunk-AJVLWNFN.js +1610 -0
  82. package/node_modules/pi-lens/dist/chunk-AJXODZY6.js +112 -0
  83. package/node_modules/pi-lens/dist/chunk-ARFCXG7S.js +84 -0
  84. package/node_modules/pi-lens/dist/chunk-AS44CFQ4.js +708 -0
  85. package/node_modules/pi-lens/dist/chunk-AWE5TMPO.js +38 -0
  86. package/node_modules/pi-lens/dist/chunk-B3I2UUT4.js +4692 -0
  87. package/node_modules/pi-lens/dist/chunk-BRJKOBZP.js +331 -0
  88. package/node_modules/pi-lens/dist/chunk-BW5KFIQC.js +59 -0
  89. package/node_modules/pi-lens/dist/chunk-C2AUYXQH.js +149 -0
  90. package/node_modules/pi-lens/dist/chunk-CGGAIP7J.js +29 -0
  91. package/node_modules/pi-lens/dist/chunk-D6QS3U6M.js +30 -0
  92. package/node_modules/pi-lens/dist/chunk-DFVMIKMQ.js +349 -0
  93. package/node_modules/pi-lens/dist/chunk-DIULIWKU.js +169 -0
  94. package/node_modules/pi-lens/dist/chunk-DQ2NZ7C4.js +2317 -0
  95. package/node_modules/pi-lens/dist/chunk-E2WFBRHM.js +213 -0
  96. package/node_modules/pi-lens/dist/chunk-E4MAEDPM.js +50 -0
  97. package/node_modules/pi-lens/dist/chunk-EOKRQ3SA.js +30 -0
  98. package/node_modules/pi-lens/dist/chunk-F3AU2TMM.js +2626 -0
  99. package/node_modules/pi-lens/dist/chunk-F3P7VQ7H.js +170 -0
  100. package/node_modules/pi-lens/dist/chunk-FC4RP4I2.js +12 -0
  101. package/node_modules/pi-lens/dist/chunk-FJNKANOS.js +32 -0
  102. package/node_modules/pi-lens/dist/chunk-GUOGVTCQ.js +146 -0
  103. package/node_modules/pi-lens/dist/chunk-GVXA6CCE.js +18 -0
  104. package/node_modules/pi-lens/dist/chunk-HHYAELLJ.js +2334 -0
  105. package/node_modules/pi-lens/dist/chunk-HMFXILPV.js +83 -0
  106. package/node_modules/pi-lens/dist/chunk-HVUZXSWK.js +421 -0
  107. package/node_modules/pi-lens/dist/chunk-HWBZIGMJ.js +62 -0
  108. package/node_modules/pi-lens/dist/chunk-I3R7GKDR.js +17 -0
  109. package/node_modules/pi-lens/dist/chunk-I7SPGOWI.js +55 -0
  110. package/node_modules/pi-lens/dist/chunk-IIXOAGHR.js +38 -0
  111. package/node_modules/pi-lens/dist/chunk-IVP5KAB7.js +2250 -0
  112. package/node_modules/pi-lens/dist/chunk-IXEBJSUE.js +22 -0
  113. package/node_modules/pi-lens/dist/chunk-JOLITGCC.js +27 -0
  114. package/node_modules/pi-lens/dist/chunk-K6VYLB2U.js +145 -0
  115. package/node_modules/pi-lens/dist/chunk-LJDODBBZ.js +78 -0
  116. package/node_modules/pi-lens/dist/chunk-LNAKEO63.js +78 -0
  117. package/node_modules/pi-lens/dist/chunk-LSMJ6KBE.js +4139 -0
  118. package/node_modules/pi-lens/dist/chunk-LW6XKDZQ.js +5565 -0
  119. package/node_modules/pi-lens/dist/chunk-N3YQJI6O.js +899 -0
  120. package/node_modules/pi-lens/dist/chunk-NABLC7W3.js +148 -0
  121. package/node_modules/pi-lens/dist/chunk-NKOUFPQF.js +659 -0
  122. package/node_modules/pi-lens/dist/chunk-NL5GLMFI.js +211 -0
  123. package/node_modules/pi-lens/dist/chunk-NMABWBZN.js +327 -0
  124. package/node_modules/pi-lens/dist/chunk-NTHH2J74.js +27 -0
  125. package/node_modules/pi-lens/dist/chunk-NTUJEGDZ.js +59 -0
  126. package/node_modules/pi-lens/dist/chunk-NXL4FFQQ.js +47 -0
  127. package/node_modules/pi-lens/dist/chunk-NXPS2L6U.js +466 -0
  128. package/node_modules/pi-lens/dist/chunk-O5WILGMI.js +42 -0
  129. package/node_modules/pi-lens/dist/chunk-O6TQT6RI.js +48 -0
  130. package/node_modules/pi-lens/dist/chunk-OAXNDZJ7.js +323 -0
  131. package/node_modules/pi-lens/dist/chunk-ODEEOXPH.js +44 -0
  132. package/node_modules/pi-lens/dist/chunk-OQGFCZJ4.js +4533 -0
  133. package/node_modules/pi-lens/dist/chunk-ORTMY4Q4.js +282 -0
  134. package/node_modules/pi-lens/dist/chunk-OS32RNR2.js +442 -0
  135. package/node_modules/pi-lens/dist/chunk-PAK6IDME.js +189 -0
  136. package/node_modules/pi-lens/dist/chunk-PWFHBTSF.js +406 -0
  137. package/node_modules/pi-lens/dist/chunk-Q5U6FMDI.js +2352 -0
  138. package/node_modules/pi-lens/dist/chunk-QOZXJ4NA.js +3364 -0
  139. package/node_modules/pi-lens/dist/chunk-QYF5S6P6.js +45 -0
  140. package/node_modules/pi-lens/dist/chunk-RIISMHKN.js +36 -0
  141. package/node_modules/pi-lens/dist/chunk-RPD4ZSB7.js +25 -0
  142. package/node_modules/pi-lens/dist/chunk-RPD5K5NC.js +79 -0
  143. package/node_modules/pi-lens/dist/chunk-RUOG5D2C.js +262 -0
  144. package/node_modules/pi-lens/dist/chunk-T4ERT73Y.js +599 -0
  145. package/node_modules/pi-lens/dist/chunk-T6D4Q4AQ.js +54 -0
  146. package/node_modules/pi-lens/dist/chunk-TGPXLY2J.js +391 -0
  147. package/node_modules/pi-lens/dist/chunk-TLGFBM3F.js +12116 -0
  148. package/node_modules/pi-lens/dist/chunk-TO6WL3GM.js +88 -0
  149. package/node_modules/pi-lens/dist/chunk-TT22N74J.js +517 -0
  150. package/node_modules/pi-lens/dist/chunk-TVN5N6GY.js +21216 -0
  151. package/node_modules/pi-lens/dist/chunk-U3VGR4VU.js +308 -0
  152. package/node_modules/pi-lens/dist/chunk-UK3CMEAL.js +1250 -0
  153. package/node_modules/pi-lens/dist/chunk-UOPVJQ4N.js +103 -0
  154. package/node_modules/pi-lens/dist/chunk-UXVNL3D7.js +23 -0
  155. package/node_modules/pi-lens/dist/chunk-UY752QSN.js +45 -0
  156. package/node_modules/pi-lens/dist/chunk-V5PXFSZK.js +188 -0
  157. package/node_modules/pi-lens/dist/chunk-V7R425XG.js +398 -0
  158. package/node_modules/pi-lens/dist/chunk-VCSRSYLF.js +81 -0
  159. package/node_modules/pi-lens/dist/chunk-VD4JQCQC.js +162 -0
  160. package/node_modules/pi-lens/dist/chunk-VDBPVIKD.js +62 -0
  161. package/node_modules/pi-lens/dist/chunk-VHQLPIRJ.js +114 -0
  162. package/node_modules/pi-lens/dist/chunk-VN2AXLEX.js +5414 -0
  163. package/node_modules/pi-lens/dist/chunk-VNMT7C64.js +478 -0
  164. package/node_modules/pi-lens/dist/chunk-WONERJTP.js +309 -0
  165. package/node_modules/pi-lens/dist/chunk-XECLWQZN.js +85 -0
  166. package/node_modules/pi-lens/dist/chunk-XIMYZ3JA.js +27 -0
  167. package/node_modules/pi-lens/dist/chunk-XK4CIILI.js +144 -0
  168. package/node_modules/pi-lens/dist/chunk-Y4T27COV.js +562 -0
  169. package/node_modules/pi-lens/dist/chunk-YGVYKNSN.js +1860 -0
  170. package/node_modules/pi-lens/dist/chunk-YLF3PPT5.js +308 -0
  171. package/node_modules/pi-lens/dist/chunk-YSNFMJKN.js +14 -0
  172. package/node_modules/pi-lens/dist/chunk-Z3CCVDUB.js +76 -0
  173. package/node_modules/pi-lens/dist/chunk-Z54ZSOBZ.js +61 -0
  174. package/node_modules/pi-lens/dist/chunk-ZAWW3AF6.js +97 -0
  175. package/node_modules/pi-lens/dist/chunk-ZMOL6RQC.js +167 -0
  176. package/node_modules/pi-lens/dist/index.js +16456 -8335
  177. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +186 -232
  178. package/node_modules/pi-lens/dist/mcp/cli.js +137 -98
  179. package/node_modules/pi-lens/dist/mcp/server.js +22589 -1573
  180. package/node_modules/pi-lens/dist/mcp/worker.js +97 -38
  181. package/node_modules/pi-lens/dist/probes/installer.js +135 -0
  182. package/node_modules/pi-lens/dist/workers/project-snapshot-persist-worker.js +22 -0
  183. package/node_modules/pi-lens/dist/workers/review-graph-persist-worker.js +15 -0
  184. package/node_modules/pi-lens/docs/agent-guide.md +13 -4
  185. package/node_modules/pi-lens/docs/agent-tools.md +42 -0
  186. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +3 -2
  187. package/node_modules/pi-lens/docs/configuration.md +20 -1
  188. package/node_modules/pi-lens/docs/environment-variables.md +52 -2
  189. package/node_modules/pi-lens/docs/features.md +8 -4
  190. package/node_modules/pi-lens/docs/globalconfig.md +1 -0
  191. package/node_modules/pi-lens/docs/io-bridge-v2-migration.md +94 -0
  192. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +36 -4
  193. package/node_modules/pi-lens/docs/lsp-idle-eviction.md +124 -0
  194. package/node_modules/pi-lens/docs/mcp.md +21 -5
  195. package/node_modules/pi-lens/docs/merge-queue-rollout.md +77 -0
  196. package/node_modules/pi-lens/docs/pi-lens-fixer.md +156 -88
  197. package/node_modules/pi-lens/docs/pi-lens-investigator.md +74 -26
  198. package/node_modules/pi-lens/docs/pi-lens-merge-policy.md +694 -0
  199. package/node_modules/pi-lens/docs/pi-lens-monitor.md +73 -7
  200. package/node_modules/pi-lens/docs/pi-lens-retro.md +6 -4
  201. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +188 -48
  202. package/node_modules/pi-lens/docs/pi-lens-subagent.md +246 -45
  203. package/node_modules/pi-lens/docs/pi-lens-warden.md +18 -7
  204. package/node_modules/pi-lens/docs/public-api-stability.md +55 -0
  205. package/node_modules/pi-lens/docs/release-qa-baseline.md +84 -17
  206. package/node_modules/pi-lens/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
  207. package/node_modules/pi-lens/docs/servercapabilities.md +53 -49
  208. package/node_modules/pi-lens/docs/settings.md +1 -0
  209. package/node_modules/pi-lens/docs/usage.md +5 -1
  210. package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm +0 -0
  211. package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm.json +3 -3
  212. package/node_modules/pi-lens/package.json +18 -6
  213. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
  214. package/node_modules/pi-lens/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
  215. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +1275 -62
  216. package/node_modules/pi-lens/scripts/download-grammars.js +5 -0
  217. package/node_modules/pi-lens/scripts/grammars.lock.json +6 -1
  218. package/node_modules/pi-lens/scripts/install-selftest.mjs +33 -34
  219. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +13 -4
  220. package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +18 -0
  221. package/package.json +15 -10
  222. package/node_modules/@dietrichgebert/ponytail/README.es.md +0 -212
  223. package/node_modules/@dietrichgebert/ponytail/README.ja.md +0 -212
  224. package/node_modules/@dietrichgebert/ponytail/README.ko.md +0 -212
  225. package/node_modules/@dietrichgebert/ponytail/README.zh-CN.md +0 -212
  226. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -35
  227. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +0 -1610
  228. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +0 -593
  229. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +0 -147
  230. package/node_modules/pi-lens/dist/clients/agent-nudge.js +0 -325
  231. package/node_modules/pi-lens/dist/clients/analysed-root.js +0 -1
  232. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +0 -731
  233. package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +0 -146
  234. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +0 -118
  235. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -10
  236. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +0 -154
  237. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +0 -75
  238. package/node_modules/pi-lens/dist/clients/atomic-write.js +0 -189
  239. package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +0 -12
  240. package/node_modules/pi-lens/dist/clients/bash-file-access.js +0 -1056
  241. package/node_modules/pi-lens/dist/clients/biome-client.js +0 -357
  242. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -837
  243. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +0 -129
  244. package/node_modules/pi-lens/dist/clients/bootstrap.js +0 -569
  245. package/node_modules/pi-lens/dist/clients/bounded-cache.js +0 -190
  246. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +0 -202
  247. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +0 -295
  248. package/node_modules/pi-lens/dist/clients/build-identity.js +0 -95
  249. package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +0 -113
  250. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +0 -105
  251. package/node_modules/pi-lens/dist/clients/bus-publish.js +0 -171
  252. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +0 -190
  253. package/node_modules/pi-lens/dist/clients/cache-manager.js +0 -524
  254. package/node_modules/pi-lens/dist/clients/cache-observability.js +0 -1313
  255. package/node_modules/pi-lens/dist/clients/call-graph.js +0 -852
  256. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +0 -422
  257. package/node_modules/pi-lens/dist/clients/cascade-budget.js +0 -196
  258. package/node_modules/pi-lens/dist/clients/cascade-format.js +0 -315
  259. package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -31
  260. package/node_modules/pi-lens/dist/clients/cascade-types.js +0 -9
  261. package/node_modules/pi-lens/dist/clients/child-unref.js +0 -124
  262. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +0 -286
  263. package/node_modules/pi-lens/dist/clients/codebase-model.js +0 -173
  264. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +0 -40
  265. package/node_modules/pi-lens/dist/clients/complexity-client.js +0 -462
  266. package/node_modules/pi-lens/dist/clients/config-core/deny.js +0 -221
  267. package/node_modules/pi-lens/dist/clients/config-core/index.js +0 -50
  268. package/node_modules/pi-lens/dist/clients/config-core/merge.js +0 -357
  269. package/node_modules/pi-lens/dist/clients/config-core/normalize.js +0 -340
  270. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +0 -248
  271. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +0 -164
  272. package/node_modules/pi-lens/dist/clients/config-core/records.js +0 -218
  273. package/node_modules/pi-lens/dist/clients/config-core/resolve.js +0 -125
  274. package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +0 -78
  275. package/node_modules/pi-lens/dist/clients/config-core/schema.js +0 -165
  276. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +0 -285
  277. package/node_modules/pi-lens/dist/clients/config-locations.js +0 -388
  278. package/node_modules/pi-lens/dist/clients/config-resolve.js +0 -798
  279. package/node_modules/pi-lens/dist/clients/config-schema.js +0 -251
  280. package/node_modules/pi-lens/dist/clients/config-warn.js +0 -407
  281. package/node_modules/pi-lens/dist/clients/console-guard-install.js +0 -26
  282. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +0 -42
  283. package/node_modules/pi-lens/dist/clients/dead-code-client.js +0 -510
  284. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -30
  285. package/node_modules/pi-lens/dist/clients/deadline-utils.js +0 -280
  286. package/node_modules/pi-lens/dist/clients/debug-handles.js +0 -211
  287. package/node_modules/pi-lens/dist/clients/debug-heap.js +0 -174
  288. package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +0 -106
  289. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +0 -426
  290. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +0 -169
  291. package/node_modules/pi-lens/dist/clients/dependency-checker.js +0 -885
  292. package/node_modules/pi-lens/dist/clients/deps/ast-grep-napi.js +0 -22
  293. package/node_modules/pi-lens/dist/clients/deps/js-yaml.js +0 -9
  294. package/node_modules/pi-lens/dist/clients/deps/minimatch.js +0 -4
  295. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +0 -14
  296. package/node_modules/pi-lens/dist/clients/deps/typebox.js +0 -14
  297. package/node_modules/pi-lens/dist/clients/deps/vscode-jsonrpc.js +0 -1
  298. package/node_modules/pi-lens/dist/clients/deps/web-tree-sitter.js +0 -24
  299. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +0 -630
  300. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +0 -305
  301. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +0 -73
  302. package/node_modules/pi-lens/dist/clients/diagnostic-tracker.js +0 -105
  303. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +0 -230
  304. package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -65
  305. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -343
  306. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -35
  307. package/node_modules/pi-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
  308. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +0 -1269
  309. package/node_modules/pi-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
  310. package/node_modules/pi-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
  311. package/node_modules/pi-lens/dist/clients/dispatch/fact-runner.js +0 -30
  312. package/node_modules/pi-lens/dist/clients/dispatch/fact-scheduler.js +0 -68
  313. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +0 -377
  314. package/node_modules/pi-lens/dist/clients/dispatch/facts/comment-facts.js +0 -22
  315. package/node_modules/pi-lens/dist/clients/dispatch/facts/file-content.js +0 -19
  316. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +0 -348
  317. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +0 -204
  318. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
  319. package/node_modules/pi-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
  320. package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +0 -339
  321. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +0 -417
  322. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +0 -89
  323. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +0 -2377
  324. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -11
  325. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +0 -87
  326. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -278
  327. package/node_modules/pi-lens/dist/clients/dispatch/priorities.js +0 -20
  328. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +0 -50
  329. package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +0 -69
  330. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +0 -135
  331. package/node_modules/pi-lens/dist/clients/dispatch/rules/async-noise.js +0 -40
  332. package/node_modules/pi-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
  333. package/node_modules/pi-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
  334. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -32
  335. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -31
  336. package/node_modules/pi-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
  337. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +0 -72
  338. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -74
  339. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
  340. package/node_modules/pi-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
  341. package/node_modules/pi-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
  342. package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
  343. package/node_modules/pi-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
  344. package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
  345. package/node_modules/pi-lens/dist/clients/dispatch/runner-context.js +0 -52
  346. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -111
  347. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
  348. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -296
  349. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -219
  350. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -82
  351. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -416
  352. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -183
  353. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -176
  354. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -164
  355. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -195
  356. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -137
  357. package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -29
  358. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -69
  359. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -167
  360. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +0 -104
  361. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -135
  362. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -91
  363. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -171
  364. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -940
  365. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -117
  366. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +0 -108
  367. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -99
  368. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -110
  369. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -379
  370. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -167
  371. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -102
  372. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +0 -414
  373. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -85
  374. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -120
  375. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -62
  376. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
  377. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +0 -169
  378. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -99
  379. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -88
  380. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -256
  381. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -173
  382. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -102
  383. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -128
  384. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -259
  385. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -183
  386. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -166
  387. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -163
  388. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -174
  389. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -168
  390. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -125
  391. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -643
  392. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -253
  393. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
  394. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
  395. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
  396. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
  397. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
  398. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
  399. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
  400. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
  401. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -15
  402. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -128
  403. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
  404. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -95
  405. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -79
  406. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +0 -79
  407. package/node_modules/pi-lens/dist/clients/dispatch/tool-profile.js +0 -30
  408. package/node_modules/pi-lens/dist/clients/dispatch/types.js +0 -21
  409. package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
  410. package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
  411. package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -32
  412. package/node_modules/pi-lens/dist/clients/disposition-publish.js +0 -124
  413. package/node_modules/pi-lens/dist/clients/durable-store.js +0 -97
  414. package/node_modules/pi-lens/dist/clients/effective-config.js +0 -415
  415. package/node_modules/pi-lens/dist/clients/env-utils.js +0 -83
  416. package/node_modules/pi-lens/dist/clients/error-class.js +0 -23
  417. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +0 -17
  418. package/node_modules/pi-lens/dist/clients/event-loop-hold.js +0 -274
  419. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +0 -250
  420. package/node_modules/pi-lens/dist/clients/extension-log.js +0 -504
  421. package/node_modules/pi-lens/dist/clients/extension-mode.js +0 -73
  422. package/node_modules/pi-lens/dist/clients/feature-hints.js +0 -103
  423. package/node_modules/pi-lens/dist/clients/file-kinds.js +0 -412
  424. package/node_modules/pi-lens/dist/clients/file-role.js +0 -134
  425. package/node_modules/pi-lens/dist/clients/file-time.js +0 -160
  426. package/node_modules/pi-lens/dist/clients/file-utils.js +0 -1032
  427. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +0 -494
  428. package/node_modules/pi-lens/dist/clients/finding-identity.js +0 -88
  429. package/node_modules/pi-lens/dist/clients/fix-worklog.js +0 -103
  430. package/node_modules/pi-lens/dist/clients/format-events-publish.js +0 -343
  431. package/node_modules/pi-lens/dist/clients/format-service.js +0 -222
  432. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +0 -9
  433. package/node_modules/pi-lens/dist/clients/formatters.js +0 -2032
  434. package/node_modules/pi-lens/dist/clients/freshness-cadence.js +0 -17
  435. package/node_modules/pi-lens/dist/clients/freshness.js +0 -38
  436. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +0 -394
  437. package/node_modules/pi-lens/dist/clients/generation-guard.js +0 -215
  438. package/node_modules/pi-lens/dist/clients/git-guard.js +0 -1136
  439. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +0 -243
  440. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +0 -509
  441. package/node_modules/pi-lens/dist/clients/go-client.js +0 -104
  442. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +0 -605
  443. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +0 -348
  444. package/node_modules/pi-lens/dist/clients/grammar-source.js +0 -465
  445. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +0 -135
  446. package/node_modules/pi-lens/dist/clients/hashline-anchor.js +0 -424
  447. package/node_modules/pi-lens/dist/clients/hook-budgets.js +0 -76
  448. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +0 -140
  449. package/node_modules/pi-lens/dist/clients/host-ports.js +0 -39
  450. package/node_modules/pi-lens/dist/clients/indent-retarget.js +0 -154
  451. package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +0 -186
  452. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +0 -156
  453. package/node_modules/pi-lens/dist/clients/installer/index.js +0 -5416
  454. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -58
  455. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +0 -783
  456. package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +0 -7
  457. package/node_modules/pi-lens/dist/clients/instance-reaper.js +0 -1137
  458. package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +0 -145
  459. package/node_modules/pi-lens/dist/clients/instance-registry.js +0 -773
  460. package/node_modules/pi-lens/dist/clients/jscpd-client.js +0 -378
  461. package/node_modules/pi-lens/dist/clients/json-cache-read.js +0 -65
  462. package/node_modules/pi-lens/dist/clients/knip-client.js +0 -788
  463. package/node_modules/pi-lens/dist/clients/language-policy.js +0 -252
  464. package/node_modules/pi-lens/dist/clients/language-profile.js +0 -361
  465. package/node_modules/pi-lens/dist/clients/language-registry.js +0 -603
  466. package/node_modules/pi-lens/dist/clients/latency-logger.js +0 -727
  467. package/node_modules/pi-lens/dist/clients/lazy-import.js +0 -21
  468. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +0 -54
  469. package/node_modules/pi-lens/dist/clients/lens-config.js +0 -404
  470. package/node_modules/pi-lens/dist/clients/lens-engine.js +0 -358
  471. package/node_modules/pi-lens/dist/clients/lens-events.js +0 -125
  472. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +0 -467
  473. package/node_modules/pi-lens/dist/clients/lens-map.js +0 -1156
  474. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +0 -74
  475. package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -222
  476. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +0 -178
  477. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +0 -421
  478. package/node_modules/pi-lens/dist/clients/lsp/client.js +0 -4593
  479. package/node_modules/pi-lens/dist/clients/lsp/config.js +0 -691
  480. package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +0 -41
  481. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +0 -225
  482. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +0 -467
  483. package/node_modules/pi-lens/dist/clients/lsp/edits.js +0 -1219
  484. package/node_modules/pi-lens/dist/clients/lsp/index.js +0 -8305
  485. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +0 -216
  486. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +0 -298
  487. package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -63
  488. package/node_modules/pi-lens/dist/clients/lsp/launch.js +0 -746
  489. package/node_modules/pi-lens/dist/clients/lsp/lombok.js +0 -158
  490. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +0 -5
  491. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -251
  492. package/node_modules/pi-lens/dist/clients/lsp/position-encoding.js +0 -61
  493. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -83
  494. package/node_modules/pi-lens/dist/clients/lsp/server.js +0 -3290
  495. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +0 -192
  496. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +0 -17
  497. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -56
  498. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +0 -332
  499. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
  500. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +0 -85
  501. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/index.js +0 -10
  502. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +0 -392
  503. package/node_modules/pi-lens/dist/clients/lsp/watch-queue.js +0 -61
  504. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
  505. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
  506. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -184
  507. package/node_modules/pi-lens/dist/clients/lsp-budget.js +0 -186
  508. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +0 -110
  509. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +0 -9
  510. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +0 -396
  511. package/node_modules/pi-lens/dist/clients/lsp-status.js +0 -59
  512. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +0 -40
  513. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +0 -420
  514. package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +0 -31
  515. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +0 -523
  516. package/node_modules/pi-lens/dist/clients/mcp/review.js +0 -197
  517. package/node_modules/pi-lens/dist/clients/mcp/session.js +0 -412
  518. package/node_modules/pi-lens/dist/clients/memory-sampler.js +0 -208
  519. package/node_modules/pi-lens/dist/clients/message-end-attribution.js +0 -30
  520. package/node_modules/pi-lens/dist/clients/metrics-client.js +0 -107
  521. package/node_modules/pi-lens/dist/clients/metrics-history.js +0 -327
  522. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +0 -263
  523. package/node_modules/pi-lens/dist/clients/model-provider.js +0 -53
  524. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +0 -189
  525. package/node_modules/pi-lens/dist/clients/module-report.js +0 -2150
  526. package/node_modules/pi-lens/dist/clients/mutating-tool.js +0 -651
  527. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +0 -368
  528. package/node_modules/pi-lens/dist/clients/mutation-bridge.js +0 -240
  529. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -734
  530. package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +0 -101
  531. package/node_modules/pi-lens/dist/clients/observed-mutation.js +0 -1253
  532. package/node_modules/pi-lens/dist/clients/oldtext-autopatch.js +0 -128
  533. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +0 -496
  534. package/node_modules/pi-lens/dist/clients/opengrep-client.js +0 -333
  535. package/node_modules/pi-lens/dist/clients/opengrep-config.js +0 -76
  536. package/node_modules/pi-lens/dist/clients/package-manager.js +0 -607
  537. package/node_modules/pi-lens/dist/clients/package-root.js +0 -38
  538. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +0 -439
  539. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +0 -43
  540. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +0 -108
  541. package/node_modules/pi-lens/dist/clients/path-utils.js +0 -1244
  542. package/node_modules/pi-lens/dist/clients/performance-report.js +0 -331
  543. package/node_modules/pi-lens/dist/clients/persist-debounce.js +0 -70
  544. package/node_modules/pi-lens/dist/clients/persistent-reverify.js +0 -271
  545. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +0 -119
  546. package/node_modules/pi-lens/dist/clients/pipeline.js +0 -1480
  547. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +0 -37
  548. package/node_modules/pi-lens/dist/clients/print-mode.js +0 -21
  549. package/node_modules/pi-lens/dist/clients/probe-home-state.js +0 -228
  550. package/node_modules/pi-lens/dist/clients/process-bridge.js +0 -66
  551. package/node_modules/pi-lens/dist/clients/process-singletons.js +0 -210
  552. package/node_modules/pi-lens/dist/clients/process-snapshot.js +0 -68
  553. package/node_modules/pi-lens/dist/clients/project-changes.js +0 -181
  554. package/node_modules/pi-lens/dist/clients/project-conventions.js +0 -171
  555. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +0 -137
  556. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +0 -109
  557. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
  558. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
  559. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
  560. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
  561. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
  562. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
  563. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
  564. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
  565. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
  566. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
  567. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
  568. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +0 -520
  569. package/node_modules/pi-lens/dist/clients/project-diagnostics/types.js +0 -1
  570. package/node_modules/pi-lens/dist/clients/project-lens-config.js +0 -807
  571. package/node_modules/pi-lens/dist/clients/project-report.js +0 -701
  572. package/node_modules/pi-lens/dist/clients/project-scale.js +0 -237
  573. package/node_modules/pi-lens/dist/clients/project-scan-policy.js +0 -11
  574. package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +0 -48
  575. package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +0 -20
  576. package/node_modules/pi-lens/dist/clients/project-snapshot.js +0 -1653
  577. package/node_modules/pi-lens/dist/clients/project-trust.js +0 -181
  578. package/node_modules/pi-lens/dist/clients/python-environment.js +0 -217
  579. package/node_modules/pi-lens/dist/clients/python-provenance.js +0 -639
  580. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +0 -47
  581. package/node_modules/pi-lens/dist/clients/quiet-window.js +0 -236
  582. package/node_modules/pi-lens/dist/clients/read-bridge.js +0 -139
  583. package/node_modules/pi-lens/dist/clients/read-expansion.js +0 -266
  584. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +0 -251
  585. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +0 -1306
  586. package/node_modules/pi-lens/dist/clients/read-guard.js +0 -1561
  587. package/node_modules/pi-lens/dist/clients/recent-touches.js +0 -240
  588. package/node_modules/pi-lens/dist/clients/redact/secrets.js +0 -449
  589. package/node_modules/pi-lens/dist/clients/resource-sampler.js +0 -628
  590. package/node_modules/pi-lens/dist/clients/reverse-deps.js +0 -270
  591. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +0 -5126
  592. package/node_modules/pi-lens/dist/clients/review-graph/format.js +0 -33
  593. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +0 -163
  594. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +0 -481
  595. package/node_modules/pi-lens/dist/clients/review-graph/persist-worker.js +0 -10
  596. package/node_modules/pi-lens/dist/clients/review-graph/query.js +0 -244
  597. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +0 -21
  598. package/node_modules/pi-lens/dist/clients/review-graph/service.js +0 -96
  599. package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -82
  600. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +0 -103
  601. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +0 -299
  602. package/node_modules/pi-lens/dist/clients/review-graph/types.js +0 -1
  603. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +0 -449
  604. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +0 -81
  605. package/node_modules/pi-lens/dist/clients/ruff-client.js +0 -179
  606. package/node_modules/pi-lens/dist/clients/rules-scanner.js +0 -131
  607. package/node_modules/pi-lens/dist/clients/run-duration.js +0 -55
  608. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +0 -746
  609. package/node_modules/pi-lens/dist/clients/runtime-config.js +0 -77
  610. package/node_modules/pi-lens/dist/clients/runtime-context.js +0 -211
  611. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +0 -1324
  612. package/node_modules/pi-lens/dist/clients/runtime-session.js +0 -2485
  613. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +0 -1295
  614. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +0 -2049
  615. package/node_modules/pi-lens/dist/clients/runtime-turn.js +0 -3767
  616. package/node_modules/pi-lens/dist/clients/rust-client.js +0 -97
  617. package/node_modules/pi-lens/dist/clients/safe-spawn.js +0 -2357
  618. package/node_modules/pi-lens/dist/clients/sanitize.js +0 -286
  619. package/node_modules/pi-lens/dist/clients/scan-utils.js +0 -25
  620. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +0 -165
  621. package/node_modules/pi-lens/dist/clients/search-read-registration.js +0 -94
  622. package/node_modules/pi-lens/dist/clients/secret-findings.js +0 -114
  623. package/node_modules/pi-lens/dist/clients/security-scan-client.js +0 -352
  624. package/node_modules/pi-lens/dist/clients/session-event-guard.js +0 -297
  625. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +0 -484
  626. package/node_modules/pi-lens/dist/clients/session-start-observability.js +0 -94
  627. package/node_modules/pi-lens/dist/clients/session-state-store.js +0 -101
  628. package/node_modules/pi-lens/dist/clients/session-summary.js +0 -15
  629. package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +0 -27
  630. package/node_modules/pi-lens/dist/clients/sg-runner.js +0 -876
  631. package/node_modules/pi-lens/dist/clients/sgconfig.js +0 -347
  632. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +0 -338
  633. package/node_modules/pi-lens/dist/clients/single-flight.js +0 -158
  634. package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +0 -108
  635. package/node_modules/pi-lens/dist/clients/skills-resolver.js +0 -141
  636. package/node_modules/pi-lens/dist/clients/slow-fs.js +0 -138
  637. package/node_modules/pi-lens/dist/clients/smells-rollup.js +0 -231
  638. package/node_modules/pi-lens/dist/clients/source-filter.js +0 -596
  639. package/node_modules/pi-lens/dist/clients/source-walker.js +0 -211
  640. package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +0 -120
  641. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +0 -110
  642. package/node_modules/pi-lens/dist/clients/stale-marker.js +0 -17
  643. package/node_modules/pi-lens/dist/clients/startup-scan.js +0 -400
  644. package/node_modules/pi-lens/dist/clients/startup-timing.js +0 -130
  645. package/node_modules/pi-lens/dist/clients/string-utils.js +0 -33
  646. package/node_modules/pi-lens/dist/clients/subagent-mode.js +0 -111
  647. package/node_modules/pi-lens/dist/clients/symbol-containment.js +0 -24
  648. package/node_modules/pi-lens/dist/clients/symbol-types.js +0 -5
  649. package/node_modules/pi-lens/dist/clients/test-runner-client.js +0 -2507
  650. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +0 -287
  651. package/node_modules/pi-lens/dist/clients/todo-scanner.js +0 -229
  652. package/node_modules/pi-lens/dist/clients/tool-agreement.js +0 -423
  653. package/node_modules/pi-lens/dist/clients/tool-config.js +0 -249
  654. package/node_modules/pi-lens/dist/clients/tool-cwd.js +0 -270
  655. package/node_modules/pi-lens/dist/clients/tool-definition.js +0 -47
  656. package/node_modules/pi-lens/dist/clients/tool-event.js +0 -105
  657. package/node_modules/pi-lens/dist/clients/tool-policy.js +0 -2755
  658. package/node_modules/pi-lens/dist/clients/tool-probe.js +0 -53
  659. package/node_modules/pi-lens/dist/clients/tool-render.js +0 -156
  660. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +0 -118
  661. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +0 -364
  662. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +0 -4195
  663. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +0 -100
  664. package/node_modules/pi-lens/dist/clients/tree-sitter-navigator.js +0 -269
  665. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +0 -569
  666. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +0 -158
  667. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
  668. package/node_modules/pi-lens/dist/clients/trivy-client.js +0 -467
  669. package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -50
  670. package/node_modules/pi-lens/dist/clients/turn-context.js +0 -52
  671. package/node_modules/pi-lens/dist/clients/turn-end/lane.js +0 -51
  672. package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -112
  673. package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +0 -204
  674. package/node_modules/pi-lens/dist/clients/turn-summary-render.js +0 -72
  675. package/node_modules/pi-lens/dist/clients/turn-summary.js +0 -132
  676. package/node_modules/pi-lens/dist/clients/typos-config.js +0 -29
  677. package/node_modules/pi-lens/dist/clients/user-notify.js +0 -51
  678. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +0 -57
  679. package/node_modules/pi-lens/dist/clients/warm-attach.js +0 -305
  680. package/node_modules/pi-lens/dist/clients/widget-state.js +0 -1808
  681. package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -49
  682. package/node_modules/pi-lens/dist/clients/word-index-store.js +0 -459
  683. package/node_modules/pi-lens/dist/clients/word-index.js +0 -2080
  684. package/node_modules/pi-lens/dist/clients/workspace-topology.js +0 -443
  685. package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +0 -65
  686. package/node_modules/pi-lens/dist/clients/zizmor-config.js +0 -340
  687. package/node_modules/pi-lens/dist/i18n.js +0 -69
  688. package/node_modules/pi-lens/dist/mcp/build-staleness.js +0 -124
  689. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +0 -583
  690. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +0 -129
  691. package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
  692. package/node_modules/pi-lens/dist/tools/activate-tools.js +0 -87
  693. package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +0 -137
  694. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +0 -244
  695. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +0 -762
  696. package/node_modules/pi-lens/dist/tools/effective-config.js +0 -90
  697. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +0 -375
  698. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +0 -2571
  699. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +0 -1745
  700. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +0 -1367
  701. package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +0 -294
  702. package/node_modules/pi-lens/dist/tools/module-report.js +0 -382
  703. package/node_modules/pi-lens/dist/tools/project-report.js +0 -86
  704. package/node_modules/pi-lens/dist/tools/render-compact.js +0 -374
  705. package/node_modules/pi-lens/dist/tools/scan-progress.js +0 -53
  706. package/node_modules/pi-lens/dist/tools/shared.js +0 -29
  707. package/node_modules/pi-lens/dist/tools/symbol-search.js +0 -155
@@ -1,1324 +0,0 @@
1
- import { randomBytes } from "node:crypto";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import { logCascade } from "./cascade-logger.js";
5
- import { appendProjectChange, } from "./project-changes.js";
6
- import { normalizeMapKey, pathsEqual } from "./path-utils.js";
7
- import { PathKeyedMap } from "./path-keyed-map.js";
8
- import { BoundedLruCache } from "./bounded-cache.js";
9
- import { PartialApplyRecordStore } from "./partial-edit-apply.js";
10
- import { ReadGuard } from "./read-guard.js";
11
- import { RUNTIME_CONFIG } from "./runtime-config.js";
12
- import { TurnSummaryCollector } from "./turn-summary.js";
13
- import { deriveProviderFromModelId } from "./model-provider.js";
14
- import { beginTurnContext, setTurnContextSession } from "./turn-context.js";
15
- import { recordDegradationOnce } from "./degradation-ledger.js";
16
- /** Keep deferred cascade admission bounded without dropping late findings. */
17
- export const MAX_PENDING_CASCADE_RUNS = 32;
18
- /**
19
- * Bounded receipt ring capacity (defect shape 9: bound the axis that grows —
20
- * per-mutation receipts are unbounded across a long session). Oldest receipts
21
- * evict first; eviction is counted and surfaced via
22
- * {@link RuntimeCoordinator.droppedMutationReceiptCount} so a consumer that
23
- * needs a complete window knows the answer was truncated, never silently
24
- * incomplete (#936 honesty rule).
25
- */
26
- const MAX_MUTATION_RECEIPTS = 512;
27
- /**
28
- * Bound on in-flight tool_call → tool_result correlations. A tool_result
29
- * follows its tool_call almost immediately, so this only needs to cover
30
- * calls genuinely in flight; sized generously above any realistic
31
- * in-flight-batch width so a slow paired result is never evicted before use.
32
- */
33
- const TOOL_CALL_ATTRIBUTION_CAPACITY = 256;
34
- /**
35
- * A recorded attribution older than this is treated as expired (as if it
36
- * were never recorded) rather than trusted — defense in depth against a host
37
- * that reuses a call id, or a pathologically delayed/duplicated tool_result,
38
- * outliving the LRU capacity bound. Generous relative to any real tool
39
- * round-trip; only guards against genuine identity reuse, not slow tools.
40
- */
41
- const TOOL_CALL_ATTRIBUTION_TTL_MS = 5 * 60_000;
42
- export class RuntimeCoordinator {
43
- _projectRoot = normalizeMapKey(process.cwd());
44
- _sessionGeneration = 0;
45
- _sessionStartedAt = Date.now();
46
- _errorDebtBaseline = null;
47
- _pipelineCrashCounts = new Map();
48
- _cachedExports = new Map();
49
- _startupScansInFlight = new Map();
50
- _cascadeRuns = [];
51
- _turnEndCascadeSettleStarts = new Map();
52
- _nextCascadeSettleToken = 0;
53
- // Cascade computes are kicked off unawaited by the pipeline (#450); their
54
- // promises park here until turn_end drains them via settleCascadeRuns. Each is
55
- // guaranteed non-rejecting by the pipeline's .catch.
56
- _pendingCascadeRuns = [];
57
- _cascadeSessionStats = {
58
- runs: 0,
59
- diagnosticsSurfaced: 0,
60
- coldSnapshotTouches: 0,
61
- };
62
- _complexityBaselines = new Map();
63
- _fixedThisTurn = new PathKeyedMap(normalizeMapKey);
64
- _writtenThisTurn = new PathKeyedMap(normalizeMapKey);
65
- _autofixDemotedThisTurn = new PathKeyedMap(normalizeMapKey);
66
- _reportedThisTurn = new Set();
67
- _mutationReceipts = [];
68
- _droppedMutationReceipts = 0;
69
- _projectRulesScan = {
70
- rules: [],
71
- hasCustomRules: false,
72
- };
73
- _telemetrySessionId = `lens-${Date.now().toString(36)}`;
74
- _lifecycleReason;
75
- _hasStableSessionId = false;
76
- _telemetryModel = "unknown";
77
- // Raw model/provider identity, separate from the combined `provider/model`
78
- // display string above — worklog/disposition attribution (#1448) wants the
79
- // two fields apart, blank when the host never supplied them. `_telemetryProvider`
80
- // is the explicit host value when given, else derived from the model id
81
- // (deriveProviderFromModelId, blank on ambiguity — never guessed).
82
- _telemetryModelId = "";
83
- _telemetryProvider = "";
84
- // True once a host has supplied an explicit provider this session. An
85
- // explicit provider is never downgraded by a derivation from a later
86
- // model-only call; a DERIVED provider, by contrast, is re-derived on
87
- // every model-only call so a mid-session model switch (e.g. gpt-5-mini →
88
- // claude-sonnet-4-5) doesn't leave a stale provider from the old model.
89
- _telemetryProviderIsExplicit = false;
90
- _turnIndex = 0;
91
- _writeIndex = 0;
92
- _projectSeq = 0;
93
- _turnStartProjectSeq = 0;
94
- _fileSeq = new Map();
95
- // File key → the projectSeq value at that file's most recent bump (#451). Lets
96
- // the review-graph builder ask "which files changed since I last built?" and
97
- // skip its per-build O(project) walk+stat sweep when only pi-observed edits
98
- // occurred. Keyed identically to _fileSeq (normalizeMapKey + path.resolve).
99
- _fileLastProjectSeq = new Map();
100
- _gitGuardHasBlockers = false;
101
- _gitGuardSummary = "";
102
- _gitGuardCacheUnknownReason;
103
- callGraph = null;
104
- wordIndex = null;
105
- _readGuard = null;
106
- _pendingDeferredMutations = new PathKeyedMap(normalizeMapKey);
107
- /** tool_call → tool_result path-attribution correlation (#1642). */
108
- _toolCallAttributions = new BoundedLruCache(TOOL_CALL_ATTRIBUTION_CAPACITY);
109
- _lspReadWarmState = new Map();
110
- _pendingInlineBlockers = new PathKeyedMap(normalizeMapKey);
111
- _actionableWarningsThisTurn = new Map();
112
- _codeQualityWarningsThisTurn = new Map();
113
- // #484: opt-in per-RUN summary of diagnostics/autofixes/formats,
114
- // accumulated across the run's turns and consumed once at the
115
- // agent_settled quiet window. The collector itself is always constructed
116
- // (cheap, empty Map) but callers gate recording behind the
117
- // `lens-turn-summary` flag so it's a true no-op when the feature is off.
118
- _turnSummary = new TurnSummaryCollector();
119
- // #2402/#1053: session-scoped applied-edit records for exact-retry
120
- // recognition. Both producers (partial-apply commit, full native-edit
121
- // success) write here; the preflight consults it before declaring an
122
- // oldText miss, so an identical retry never re-executes a committed write.
123
- partialApplyRecords = new PartialApplyRecordStore();
124
- resetForSession(startedAt = Date.now()) {
125
- this._sessionGeneration += 1;
126
- this._sessionStartedAt = startedAt;
127
- this._complexityBaselines.clear();
128
- this._pipelineCrashCounts.clear();
129
- this._cachedExports.clear();
130
- this.wordIndex = null;
131
- this._startupScansInFlight.clear();
132
- this._cascadeRuns = [];
133
- this._pendingCascadeRuns = [];
134
- this._turnEndCascadeSettleStarts.clear();
135
- this._cascadeSessionStats = {
136
- runs: 0,
137
- diagnosticsSurfaced: 0,
138
- coldSnapshotTouches: 0,
139
- };
140
- this._fixedThisTurn.clear();
141
- this._writtenThisTurn.clear();
142
- this._autofixDemotedThisTurn.clear();
143
- this._reportedThisTurn.clear();
144
- this._mutationReceipts = [];
145
- this._droppedMutationReceipts = 0;
146
- this._telemetrySessionId = `lens-${Date.now().toString(36)}-${randomBytes(4).toString("hex")}`;
147
- this._hasStableSessionId = false;
148
- this._telemetryModel = "unknown";
149
- this._telemetryModelId = "";
150
- this._telemetryProvider = "";
151
- this._telemetryProviderIsExplicit = false;
152
- this._turnIndex = 0;
153
- this._writeIndex = 0;
154
- this._projectSeq = 0;
155
- this._turnStartProjectSeq = 0;
156
- this._fileSeq.clear();
157
- this._fileLastProjectSeq.clear();
158
- this._gitGuardHasBlockers = false;
159
- this._gitGuardSummary = "";
160
- this._gitGuardCacheUnknownReason = undefined;
161
- this._readGuard = null;
162
- this._pendingDeferredMutations.clear();
163
- // #1642 F5: every sibling correlation/state map is cleared here. A
164
- // per-session-numbered host reusing tool-call ids across sessions must
165
- // not let a NEW session inherit a DEAD session's recorded skip verdict.
166
- this._toolCallAttributions.clear();
167
- this._lspReadWarmState.clear();
168
- this._pendingInlineBlockers.clear();
169
- this._actionableWarningsThisTurn.clear();
170
- this._codeQualityWarningsThisTurn.clear();
171
- this._turnSummary.clear();
172
- // #2402: an applied-edit record is a fact about the session that applied
173
- // it; a new session must re-resolve identical payloads from content.
174
- this.partialApplyRecords.clear();
175
- }
176
- get sessionStartedAt() {
177
- return this._sessionStartedAt;
178
- }
179
- get cascadeSessionStats() {
180
- return this._cascadeSessionStats;
181
- }
182
- recordCascadeRun(diagnosticsSurfaced, coldSnapshotTouches) {
183
- this._cascadeSessionStats.runs += 1;
184
- this._cascadeSessionStats.diagnosticsSurfaced += diagnosticsSurfaced;
185
- this._cascadeSessionStats.coldSnapshotTouches += coldSnapshotTouches;
186
- }
187
- /**
188
- * Record the turn-end policy verdict on every live inline-blocker record
189
- * (#3248): `true` for a file whose every blocker the policy suppressed,
190
- * `false` for every other record in the map.
191
- *
192
- * ONE writer, rewriting the WHOLE axis each turn end, so the verdict can
193
- * never outlive the pass that made it: a record demoted since, or one whose
194
- * survivors came back because the file's bytes moved under a content-bound
195
- * anchor, is cleared by the same call that sets its sibling. A fresh
196
- * dispatch replaces the record wholesale (`recordInlineBlockers`), so a NEW
197
- * blocker is never born pre-suppressed (#1198 ordering).
198
- *
199
- * @returns how many records this call CHANGED — 0 means the gate's view of
200
- * the map is already what the policy just decided.
201
- */
202
- applyInlineBlockerPolicyVerdicts(suppressedFilePaths) {
203
- const suppressed = new Set(suppressedFilePaths.map((filePath) => path.resolve(filePath)));
204
- let changed = 0;
205
- for (const [key, entry] of this._pendingInlineBlockers.entries()) {
206
- const policySuppressed = suppressed.has(path.resolve(entry.filePath));
207
- if (!!entry.policySuppressed === policySuppressed)
208
- continue;
209
- this._pendingInlineBlockers.set(key, { ...entry, policySuppressed });
210
- changed += 1;
211
- }
212
- return changed;
213
- }
214
- updateGitGuardStatus(hasBlockers, output) {
215
- // The status is an aggregate over the current per-file map. A clean B
216
- // result must not erase an unresolved A result; the pipeline records/clears
217
- // the edited file immediately before this method runs.
218
- // #3248: every live record except one whose whole blocker set the
219
- // turn-end disposition policy suppressed. The record itself stays in the
220
- // map — the policy is content-bound and re-derived from the record's
221
- // diagnostics at every turn end, so dropping it there would be silencing
222
- // rather than filtering (AGENTS.md shape 10); it just stops counting for
223
- // the gate the agent was shown nothing for.
224
- const blocking = this.getInlineBlockersSnapshot().filter((entry) => !entry.policySuppressed);
225
- this._gitGuardHasBlockers = hasBlockers || blocking.length > 0;
226
- if (!this._gitGuardHasBlockers) {
227
- this._gitGuardSummary = "";
228
- return;
229
- }
230
- const firstLine = output
231
- .split("\n")
232
- .map((line) => line.trim())
233
- .find((line) => line.length > 0);
234
- const summaries = blocking
235
- .map((entry) => entry.summary.trim())
236
- .filter(Boolean);
237
- this._gitGuardSummary = (summaries[0] ??
238
- firstLine ??
239
- "Unresolved blockers detected").slice(0, 160);
240
- }
241
- get gitGuardHasBlockers() {
242
- return this._gitGuardHasBlockers;
243
- }
244
- get gitGuardSummary() {
245
- return this._gitGuardSummary;
246
- }
247
- markGitGuardCacheUnknown(reason) {
248
- this._gitGuardCacheUnknownReason = reason;
249
- }
250
- clearGitGuardCacheUnknown() {
251
- this._gitGuardCacheUnknownReason = undefined;
252
- }
253
- get gitGuardCacheUnknownReason() {
254
- return this._gitGuardCacheUnknownReason;
255
- }
256
- beginTurn() {
257
- // #1443: runs sitting here at turn_start were appended AFTER the last
258
- // turn_end drained them (consumeCascadeRuns) — the quiet-window reconcile's
259
- // late re-injection (`onResolvedFound`, clients/lsp/cascade-tier.ts) lands
260
- // in exactly that window. Wiping them dead-ended that delivery path: the
261
- // finding was computed, formatted, appended, and then deleted before any
262
- // turn_end could render it. Carry them into THIS turn instead, exactly
263
- // once: `carriedTurns` is stamped on the way through and a run that the
264
- // next turn_end still did not consume is dropped here with a log line
265
- // rather than queued forever (a stale finding must not outlive the state
266
- // it describes, and an unbounded queue would replay it every turn).
267
- this._cascadeRuns = this._cascadeRuns.flatMap((run) => {
268
- const carriedTurns = (run.carriedTurns ?? 0) + 1;
269
- if (carriedTurns > 1) {
270
- logCascade({
271
- phase: "cascade_carry_over_drop",
272
- filePath: run.filePath,
273
- neighborCount: run.neighborCount,
274
- diagnosticCount: run.diagnosticCount,
275
- metadata: { carriedTurns, turnIndex: this._turnIndex },
276
- });
277
- return [];
278
- }
279
- return [{ ...run, carriedTurns }];
280
- });
281
- // _pendingCascadeRuns is deliberately NOT cleared here: a cascade compute
282
- // still in flight past last turn_end's settle cap (fresh graph builds have
283
- // measured up to ~19s) must surface on the NEXT turn_end, not be dropped —
284
- // pre-#450 those findings were always awaited, never lost. Session reset
285
- // still clears it.
286
- // Inline blockers are session-scoped per-file state. They are cleared only
287
- // when that file is re-analyzed clean or the session resets; a new turn must
288
- // not let a clean unrelated file erase an unresolved blocker.
289
- this._actionableWarningsThisTurn.clear();
290
- this._codeQualityWarningsThisTurn.clear();
291
- // _turnSummary is deliberately NOT cleared here (#484 rework): the
292
- // summary entry is emitted once per RUN at the agent_settled quiet
293
- // window (sendMessage during a live stream would STEER the agent, and
294
- // turn_end can fire mid-stream), so the collector must accumulate
295
- // across the run's turns. It is cleared only by consume() at emit and
296
- // by resetForSession().
297
- this._turnStartProjectSeq = this._projectSeq;
298
- this._turnIndex += 1;
299
- beginTurnContext(this._telemetrySessionId);
300
- this._writeIndex = 0;
301
- this._reportedThisTurn.clear();
302
- this._writtenThisTurn.clear();
303
- this._autofixDemotedThisTurn.clear();
304
- }
305
- /**
306
- * THE one mutation seam. Every producer of an in-project file mutation —
307
- * native write/edit, recognized bash writes, format/autofix, LSP workspace
308
- * edits, and (phase 2) opaque script-write recovery — records through here,
309
- * once: it bumps the seq store (`bumpFileSeq`), appends a bounded attributed
310
- * receipt, and optionally appends the durable change-log entry. Consumers
311
- * derive from `getFilesChangedSince` / `getMutationsSince`; no producer or
312
- * consumer may hand-roll a parallel bump+log pairing (#2000 phase 1).
313
- *
314
- * Receipt recording never throws; change-log append failures route to
315
- * `onAppendError` (default: swallowed) so telemetry cannot break dispatch.
316
- */
317
- recordProjectMutation(args) {
318
- const { projectSeq, fileSeq, key } = this.bumpFileSeq(args.filePath);
319
- if (this._mutationReceipts.length >= MAX_MUTATION_RECEIPTS) {
320
- this._mutationReceipts.shift();
321
- this._droppedMutationReceipts += 1;
322
- }
323
- this._mutationReceipts.push({
324
- seq: projectSeq,
325
- // Reuse the bump's normalized key (a realpath syscall: ~200us on
326
- // Windows, ~1.8us on POSIX since #3098) — never re-derive it here.
327
- filePath: key,
328
- source: args.source,
329
- turnIndex: this._turnIndex,
330
- ts: Date.now(),
331
- });
332
- if (args.cwd !== undefined) {
333
- try {
334
- appendProjectChange(args.cwd, {
335
- seq: projectSeq,
336
- timestamp: new Date().toISOString(),
337
- sessionId: this.telemetrySessionId,
338
- turnIndex: this.turnIndex,
339
- source: args.source,
340
- filePath: path.resolve(args.filePath),
341
- fileSeq,
342
- changedRange: args.changedRange,
343
- });
344
- }
345
- catch (err) {
346
- args.onAppendError?.(err);
347
- }
348
- }
349
- return { projectSeq, fileSeq };
350
- }
351
- /**
352
- * Attributed mutations whose seq is strictly after `seq` — the receipt-level
353
- * counterpart of {@link getFilesChangedSince}. Bounded: entries evicted by
354
- * the ring cap are gone; compare `droppedMutationReceiptCount` against zero
355
- * before treating the result as a complete window.
356
- */
357
- getMutationsSince(seq) {
358
- // Shallow copies: a consumer mutating a returned receipt must not
359
- // corrupt the ring's internal state.
360
- return this._mutationReceipts
361
- .filter((r) => r.seq > seq)
362
- .map((r) => ({ ...r }));
363
- }
364
- get droppedMutationReceiptCount() {
365
- return this._droppedMutationReceipts;
366
- }
367
- /**
368
- * Atomically records write/edit ordering before debounce can coalesce it.
369
- *
370
- * Takes the classified {@link MutationKind}, not a raw tool name (#2423):
371
- * an edit-shaped tool pi-lens does not name still demotes this file to the
372
- * deferred pass, which is the safe timing.
373
- */
374
- recordMutationToolReceipt(filePath, kind) {
375
- if (kind === "write") {
376
- this._writtenThisTurn.set(filePath, true);
377
- }
378
- else if (this._writtenThisTurn.has(filePath)) {
379
- this._autofixDemotedThisTurn.set(filePath, true);
380
- // A later edit establishes a new final state that must be eligible for
381
- // the deferred pass even if the preceding write was fixed immediately.
382
- this._fixedThisTurn.delete(filePath);
383
- }
384
- return {
385
- autofixMode: kind === "edit" || this._autofixDemotedThisTurn.has(filePath)
386
- ? "deferred"
387
- : "immediate",
388
- };
389
- }
390
- get reportedThisTurn() {
391
- return this._reportedThisTurn;
392
- }
393
- nextWriteIndex() {
394
- this._writeIndex += 1;
395
- return this._writeIndex;
396
- }
397
- peekWriteIndex() {
398
- return this._writeIndex;
399
- }
400
- setTelemetryIdentity(identity) {
401
- if (identity.sessionId && identity.sessionId.trim()) {
402
- this._telemetrySessionId = identity.sessionId.trim();
403
- setTurnContextSession(this._telemetrySessionId);
404
- }
405
- const model = identity.model?.trim();
406
- const provider = identity.provider?.trim();
407
- if (model && provider) {
408
- this._telemetryModel = `${provider}/${model}`;
409
- }
410
- else if (model) {
411
- this._telemetryModel = model;
412
- }
413
- else if (provider) {
414
- this._telemetryModel = provider;
415
- }
416
- if (model)
417
- this._telemetryModelId = model;
418
- if (provider) {
419
- this._telemetryProvider = provider;
420
- this._telemetryProviderIsExplicit = true;
421
- }
422
- else if (model && !this._telemetryProviderIsExplicit) {
423
- // No explicit provider has ever been reported this session, so the
424
- // provider is (still) a derivation — re-derive it from the CURRENT
425
- // model id every time. Without this, a stale derived provider from
426
- // an earlier model would survive a mid-session model switch (e.g.
427
- // gpt-5-mini → claude-sonnet-4-5 with no explicit provider on
428
- // either call) because the old "has any provider ever been set"
429
- // guard treated the derived value as sticky. An explicit provider,
430
- // once set, is never touched here regardless of later model calls.
431
- this._telemetryProvider = deriveProviderFromModelId(model);
432
- }
433
- }
434
- get telemetrySessionId() {
435
- return this._telemetrySessionId;
436
- }
437
- /**
438
- * Pin the session identity to pi's STABLE session id and record why this
439
- * session started (#190). Called AFTER {@link resetForSession} (which assigns
440
- * a fresh random id), so the stable id — when pi provides one via
441
- * `ctx.sessionManager.getSessionId()` — wins and survives a quit→resume.
442
- */
443
- setSessionLifecycle(args) {
444
- if (args.sessionId && args.sessionId.trim()) {
445
- this._telemetrySessionId = args.sessionId.trim();
446
- this._hasStableSessionId = true;
447
- }
448
- this._lifecycleReason = args.reason;
449
- }
450
- /** Why the current session started: new | resume | fork | reload | startup. */
451
- get sessionLifecycleReason() {
452
- return this._lifecycleReason;
453
- }
454
- /** True once a stable pi session id has been pinned (vs the random fallback). */
455
- get hasStableSessionId() {
456
- return this._hasStableSessionId;
457
- }
458
- get telemetryModel() {
459
- return this._telemetryModel;
460
- }
461
- /** Raw model id (never the combined `provider/model` display string), blank
462
- * when the host hasn't reported one this session. Worklog/disposition
463
- * attribution (#1448) reads this, not {@link telemetryModel}. */
464
- get telemetryModelId() {
465
- return this._telemetryModelId;
466
- }
467
- /** Explicit host-reported provider, or a conservative derivation from the
468
- * model id (see clients/model-provider.ts), blank when neither is known. */
469
- get telemetryProviderId() {
470
- return this._telemetryProvider;
471
- }
472
- get turnIndex() {
473
- return this._turnIndex;
474
- }
475
- get projectSeq() {
476
- return this._projectSeq;
477
- }
478
- get turnStartProjectSeq() {
479
- return this._turnStartProjectSeq;
480
- }
481
- seedProjectSequence(projectSeq, fileSeqByPath) {
482
- this._projectSeq = Math.max(0, Math.floor(projectSeq));
483
- this._turnStartProjectSeq = this._projectSeq;
484
- this._fileSeq.clear();
485
- // Seeded per-file counters carry no projectSeq provenance, so start the
486
- // changed-since map empty; the graph fast path simply won't fire until an
487
- // in-process bump records a seq-stamped change (safe: falls back to sweep).
488
- this._fileLastProjectSeq.clear();
489
- for (const [filePath, seq] of fileSeqByPath ?? []) {
490
- this._fileSeq.set(normalizeMapKey(path.resolve(filePath)), Math.max(0, seq));
491
- }
492
- }
493
- bumpFileSeq(filePath) {
494
- // normalizeMapKey costs a realpath syscall per call — ~200us on Windows,
495
- // ~1.8us on POSIX since #3098; every caller that also needs the key must
496
- // reuse this one instead of paying it twice.
497
- const key = normalizeMapKey(path.resolve(filePath));
498
- this._projectSeq += 1;
499
- const fileSeq = (this._fileSeq.get(key) ?? 0) + 1;
500
- this._fileSeq.set(key, fileSeq);
501
- this._fileLastProjectSeq.set(key, this._projectSeq);
502
- return { projectSeq: this._projectSeq, fileSeq, key };
503
- }
504
- /**
505
- * Files whose most recent bump happened AFTER `seq` — i.e. every file the
506
- * review graph would need to re-ingest to catch up from a build taken at
507
- * projectSeq `seq` (#451). Returns NORMALIZED keys (normalizeMapKey +
508
- * path.resolve), the same form the builder's fileSignatures map uses, so the
509
- * caller can compare without re-normalizing.
510
- */
511
- getFilesChangedSince(seq) {
512
- const changed = [];
513
- for (const [key, lastSeq] of this._fileLastProjectSeq) {
514
- if (lastSeq > seq)
515
- changed.push(key);
516
- }
517
- return changed;
518
- }
519
- getFileSeq(filePath) {
520
- return this._fileSeq.get(normalizeMapKey(path.resolve(filePath))) ?? 0;
521
- }
522
- getFileSeqEntries() {
523
- return [...this._fileSeq.entries()];
524
- }
525
- get sessionGeneration() {
526
- return this._sessionGeneration;
527
- }
528
- isCurrentSession(generation) {
529
- return this._sessionGeneration === generation;
530
- }
531
- markStartupScanInFlight(name, generation) {
532
- this._startupScansInFlight.set(name, generation);
533
- }
534
- clearStartupScanInFlight(name, generation) {
535
- const owner = this._startupScansInFlight.get(name);
536
- if (owner === generation) {
537
- this._startupScansInFlight.delete(name);
538
- }
539
- }
540
- isStartupScanInFlight(name) {
541
- return this._startupScansInFlight.has(name);
542
- }
543
- formatPipelineCrashNotice(filePath, err) {
544
- const key = path.resolve(filePath);
545
- const count = (this._pipelineCrashCounts.get(key) ?? 0) + 1;
546
- this._pipelineCrashCounts.set(key, count);
547
- const message = err instanceof Error ? err.message : String(err);
548
- const shortMessage = message.split("\n")[0].slice(0, 220);
549
- const shouldSurface = count <= RUNTIME_CONFIG.crashNotice.alwaysShowFirstN ||
550
- count % RUNTIME_CONFIG.crashNotice.showEveryNth === 0;
551
- if (!shouldSurface)
552
- return "";
553
- return [
554
- "⚠️ pi-lens pipeline crashed while analyzing this write.",
555
- `File: ${path.basename(filePath)} | crash count this session: ${count}`,
556
- `Error: ${shortMessage}`,
557
- "Recovery: LSP service was reset. If this repeats, rerun with --no-lsp and report the file + stack.",
558
- ].join("\n");
559
- }
560
- getCrashEntries() {
561
- return Array.from(this._pipelineCrashCounts.entries());
562
- }
563
- get projectRoot() {
564
- return this._projectRoot;
565
- }
566
- set projectRoot(value) {
567
- this._projectRoot = normalizeMapKey(value);
568
- }
569
- get errorDebtBaseline() {
570
- return this._errorDebtBaseline;
571
- }
572
- set errorDebtBaseline(value) {
573
- this._errorDebtBaseline = value;
574
- }
575
- get cachedExports() {
576
- return this._cachedExports;
577
- }
578
- appendCascadeRun(run) {
579
- this._cascadeRuns.push(run);
580
- }
581
- appendCascadePromise(p) {
582
- if (this._pendingCascadeRuns.length < MAX_PENDING_CASCADE_RUNS) {
583
- this._pendingCascadeRuns.push(p);
584
- return;
585
- }
586
- // Preserve delivery for overflow rather than growing the per-edit array.
587
- // The settled run enters the same accumulator off-hook and is therefore
588
- // visible to the next turn-end drain.
589
- recordDegradationOnce({
590
- kind: "cascade-pending-cap",
591
- subject: "runtime-coordinator",
592
- reason: `deferred cascade admission capped at ${MAX_PENDING_CASCADE_RUNS}`,
593
- });
594
- void p
595
- .then((run) => this.appendCascadeRun(run))
596
- .catch(() => {
597
- // Pipeline promises are normally non-rejecting; preserve the existing
598
- // failure sink if a caller violates that contract.
599
- });
600
- }
601
- /**
602
- * The active turn_end settle clock, or undefined outside that wait.
603
- *
604
- * #1462 review F-F: every cascade compute in flight on this coordinator
605
- * reads the SAME clock. `_turnEndCascadeSettleStarts` is keyed by settle
606
- * token so `settleCascadeRuns` can distinguish its own drain from a nested
607
- * one, but this getter always answers with the latest active window —
608
- * there is one turn_end per runtime, not one per caller. A cascade begun
609
- * moments before turn_end and one begun long before it both measure elapsed
610
- * time against the same start, which is correct: they are racing the same
611
- * settle wait and share its deadline, not separate ones.
612
- */
613
- getTurnEndCascadeSettleStart() {
614
- let latest;
615
- for (const start of this._turnEndCascadeSettleStarts.values())
616
- latest = start;
617
- return latest;
618
- }
619
- /**
620
- * Drain the deferred cascade computes kicked off this turn (#450), racing them
621
- * against a bounded wait. Fulfilled runs feed the same accumulator as inline
622
- * runs (appendCascadeRun). A promise still pending at the cap is retained so a
623
- * late-resolving compute is picked up on the next turn_end rather than lost.
624
- * The stored promises never reject (pipeline guarantees an "error" skip-run).
625
- */
626
- async settleCascadeRuns(maxWaitMs, settleOptions = {}) {
627
- const pending = this._pendingCascadeRuns;
628
- if (pending.length === 0)
629
- return { settled: 0, timedOut: 0 };
630
- this._pendingCascadeRuns = [];
631
- const settleToken = settleOptions.trackTurnEndClock
632
- ? ++this._nextCascadeSettleToken
633
- : undefined;
634
- if (settleToken !== undefined) {
635
- this._turnEndCascadeSettleStarts.set(settleToken, Date.now());
636
- }
637
- try {
638
- // Track per-promise settlement so promises still in flight at the cap can be
639
- // carried over. A settled entry records its run; an unsettled one is re-parked.
640
- const tracked = pending.map((p) => {
641
- const entry = { done: false, promise: p };
642
- entry.promise = p.then((run) => {
643
- entry.done = true;
644
- entry.run = run;
645
- return run;
646
- });
647
- return entry;
648
- });
649
- const timeout = new Promise((resolve) => {
650
- setTimeout(resolve, maxWaitMs).unref?.();
651
- });
652
- await Promise.race([
653
- Promise.allSettled(tracked.map((t) => t.promise)),
654
- timeout,
655
- ]);
656
- let settled = 0;
657
- let timedOut = 0;
658
- for (const entry of tracked) {
659
- if (entry.done && entry.run) {
660
- this.appendCascadeRun(entry.run);
661
- settled += 1;
662
- }
663
- else {
664
- this._pendingCascadeRuns.push(entry.promise);
665
- timedOut += 1;
666
- }
667
- }
668
- return { settled, timedOut };
669
- }
670
- finally {
671
- if (settleToken !== undefined) {
672
- this._turnEndCascadeSettleStarts.delete(settleToken);
673
- }
674
- }
675
- }
676
- consumeCascadeRuns() {
677
- const runs = this._cascadeRuns;
678
- this._cascadeRuns = [];
679
- return runs;
680
- }
681
- /**
682
- * R1 (#1443 follow-up): non-destructive peek used by turn_end's read-only
683
- * fast path. A carried cascade run (or one still in flight) represents a
684
- * DELIVERY OPPORTUNITY, not turn activity — an agent that answers a question
685
- * without editing anything must still get yesterday's late finding. Before
686
- * this, the files-empty early return skipped `settleCascadeRuns` /
687
- * `consumeCascadeRuns` entirely on a read-only turn, so `beginTurn`'s next
688
- * carry pass saw the run as having survived a turn_start with no offsetting
689
- * drain and dropped it — burning the one-turn carry allowance on a turn that
690
- * never had a chance to deliver.
691
- */
692
- hasCascadeRuns() {
693
- // Carried, ALREADY-BUILT runs only. Pending (still-settling) computes are
694
- // deliberately excluded: a read-only turn that fell through for a pending
695
- // run would block on the full settle cap — every turn, forever, when the
696
- // compute never resolves (re-review finding F1). A pending run loses
697
- // nothing by waiting: settleCascadeRuns re-parks it and the next turn
698
- // that actually settles it delivers it.
699
- return this._cascadeRuns.length > 0;
700
- }
701
- recordInlineBlockers(filePath, summary, writeIndex, sources, lines, contentBaseline, diagnostics) {
702
- const recordedAtMs = Date.now();
703
- this._pendingInlineBlockers.set(path.resolve(filePath), {
704
- filePath,
705
- summary,
706
- writeIndex,
707
- sources,
708
- lines,
709
- diagnostics,
710
- recordedAtMs,
711
- stale: false,
712
- ...(contentBaseline
713
- ? {
714
- recordedSize: contentBaseline.size,
715
- recordedHash: contentBaseline.sha256,
716
- }
717
- : {}),
718
- });
719
- return recordedAtMs;
720
- }
721
- clearInlineBlockers(filePath) {
722
- this._pendingInlineBlockers.delete(path.resolve(filePath));
723
- }
724
- /**
725
- * #1631: demote a cached blocker to stale without dropping it (#1419
726
- * demote-not-drop). Called by the turn-boundary freshness sweep when the
727
- * file or one of its forward imports drifted on disk after the verdict.
728
- * Idempotent: re-marking an already-stale entry (for ANY reason) is a
729
- * no-op — a `"past-eof"` demotion already took this record out of the
730
- * authoritative channel, and `sweepInlineBlockerFreshness` re-checks next
731
- * turn once that heals. Returns true only when this call transitioned the
732
- * entry to stale, so a caller can log the demotion exactly once.
733
- */
734
- markInlineBlockerStale(filePath, reason = "dependency-drift") {
735
- const key = path.resolve(filePath);
736
- const existing = this._pendingInlineBlockers.get(key);
737
- if (!existing || existing.stale)
738
- return false;
739
- this._pendingInlineBlockers.set(key, {
740
- ...existing,
741
- stale: true,
742
- staleReason: reason,
743
- });
744
- return true;
745
- }
746
- /**
747
- * #1641: re-derive the past-EOF demotion for one inline-blocker record.
748
- * Unlike {@link markInlineBlockerStale} (a one-way latch for the
749
- * dependency-drift gate), this RE-ARMS: called every turn end with the
750
- * gate's freshly-computed verdict, it can both demote (rising edge) and
751
- * heal (falling edge — a transient shrink-then-restore of the file). Never
752
- * touches a record a sibling gate demoted (`staleReason !== "past-eof"`
753
- * while `stale`) — composing with #1631's dependency-drift gate means each
754
- * gate only heals its own demotions. Returns true only on an actual
755
- * transition, so the caller logs/resyncs exactly once per edge.
756
- */
757
- setInlineBlockerPastEofStale(filePath, isPastEof) {
758
- const key = path.resolve(filePath);
759
- const existing = this._pendingInlineBlockers.get(key);
760
- if (!existing)
761
- return false;
762
- if (existing.stale && existing.staleReason !== "past-eof")
763
- return false;
764
- const currentlyPastEof = !!existing.stale && existing.staleReason === "past-eof";
765
- if (currentlyPastEof === isPastEof)
766
- return false;
767
- this._pendingInlineBlockers.set(key, {
768
- ...existing,
769
- stale: isPastEof,
770
- staleReason: isPastEof ? "past-eof" : undefined,
771
- });
772
- return true;
773
- }
774
- /**
775
- * #2982: re-derive the self-drift demotion for one inline-blocker record.
776
- *
777
- * Modelled on {@link setInlineBlockerPastEofStale}, not on
778
- * {@link markInlineBlockerStale}: it RE-ARMS rather than latching, so a
779
- * file whose bytes drift and then come back (a checkout, a revert, an
780
- * editor writing the original content) un-demotes on the next sweep
781
- * instead of staying demoted for the session. That re-arm is what lets
782
- * this axis skip the #1950 delivery cap entirely — a record that can heal
783
- * needs no bounded-noise retirement, and applying the cap here would walk
784
- * an ast-grep or tree-sitter security finding out of turn-end rendering
785
- * permanently (#2982 review).
786
- *
787
- * Composes with the sibling gates the same way they compose with each
788
- * other: it never touches a record another gate demoted, and never heals a
789
- * demotion it did not make. Returns true only on an actual transition, so
790
- * the caller counts exactly one edge.
791
- */
792
- setInlineBlockerSelfDriftStale(filePath, isSelfDrift) {
793
- const key = path.resolve(filePath);
794
- const existing = this._pendingInlineBlockers.get(key);
795
- if (!existing)
796
- return false;
797
- if (existing.stale && existing.staleReason !== "self-drift")
798
- return false;
799
- const currentlySelfDrift = !!existing.stale && existing.staleReason === "self-drift";
800
- if (currentlySelfDrift === isSelfDrift)
801
- return false;
802
- // Omit the key rather than assigning `undefined` to it: under
803
- // `exactOptionalPropertyTypes` those are different, and writing the
804
- // `undefined` is a strictness spike the ratchet counts. Healing has to
805
- // drop `staleReason` off the rebuilt record, so destructure it away
806
- // instead of letting `...existing` carry the old value through.
807
- const { staleReason: _cleared, ...rest } = existing;
808
- this._pendingInlineBlockers.set(key, {
809
- ...rest,
810
- stale: isSelfDrift,
811
- ...(isSelfDrift ? { staleReason: "self-drift" } : {}),
812
- });
813
- return true;
814
- }
815
- /**
816
- * #1944: retire a past-EOF demotion after its ONE degraded delivery.
817
- *
818
- * The past-EOF gate demotes and re-arms, but nothing ever retired the
819
- * record, so a blocker whose file shrank past the cited lines re-served on
820
- * every turn end for the rest of the session — measured live at 80+
821
- * minutes on session 01a0234c. The re-serve is unbounded, not the six
822
- * turns the first evidence window suggested.
823
- *
824
- * It is unbounded because the record cannot resolve itself. The two
825
- * clearing events (`clearInlineBlockers` on a later dispatch of the same
826
- * path, `retireInlineBlockerOnConfirmedClean` on a fresh clean verdict)
827
- * both need the file to be looked at again, and the agent has no reason to
828
- * look: the coordinates it was handed do not exist. "Re-run to confirm" is
829
- * an instruction this record makes impossible to follow.
830
- *
831
- * So the delivery surface retires it after serving it once, degraded. That
832
- * is a DROP, which #1419's demote-not-drop rule normally forbids; the
833
- * exception is narrow and stated here. The finding was already delivered
834
- * this turn with its dead coordinates annotated, and what remains is a
835
- * message pinned to a line the file does not have. `deadLines` is required
836
- * and must be non-empty, so a record stale for any OTHER reason, or
837
- * past-EOF with no identified dead line, still stands.
838
- *
839
- * @returns true when an entry was retired — the caller records it, so the
840
- * suppression is never silent (#1432 Gap 1).
841
- */
842
- retireDemotedPastEofBlocker(filePath, deadLines) {
843
- if (deadLines.length === 0)
844
- return false;
845
- const key = path.resolve(filePath);
846
- const existing = this._pendingInlineBlockers.get(key);
847
- if (!existing)
848
- return false;
849
- // Only this gate's own demotion. A dependency-drift demotion (#1631)
850
- // keeps in-bounds coordinates the agent CAN re-run against, so it stays
851
- // in the store until a fresh verdict clears it.
852
- if (!existing.stale)
853
- return false;
854
- if ((existing.staleReason ?? "past-eof") !== "past-eof")
855
- return false;
856
- this._pendingInlineBlockers.delete(key);
857
- return true;
858
- }
859
- /**
860
- * #1950 fix-round F1: read the current delivery count WITHOUT committing
861
- * an increment. `runtime-turn.ts` needs the count a delivery would reach
862
- * BEFORE it knows whether that delivery will actually reach the agent —
863
- * the turn-end signature dedupe (`turn-end-findings-last`) can suppress a
864
- * turn whose rendered content is identical to the last one, and a
865
- * suppressed turn must not advance the counter (the agent never saw it).
866
- * The caller peeks, renders the tentative body, and only calls
867
- * {@link incrementInlineBlockerStaleDelivery} once it knows the turn's
868
- * content is NOT being suppressed.
869
- */
870
- peekInlineBlockerStaleDeliveryCount(filePath) {
871
- const key = path.resolve(filePath);
872
- return this._pendingInlineBlockers.get(key)?.staleDeliveryCount ?? 0;
873
- }
874
- /**
875
- * #1950: commit one more turn end that re-served this record while
876
- * `stale`. The caller (`runtime-turn.ts`) only calls this for a
877
- * `"dependency-drift"` demotion — a `"past-eof"` demotion retires after
878
- * its own single delivery (#1944, `retireDemotedPastEofBlocker`) and
879
- * never accumulates a count — and only AFTER confirming the turn's
880
- * content will not be suppressed by the signature dedupe (see
881
- * {@link peekInlineBlockerStaleDeliveryCount}), so this counts ACTUAL
882
- * deliveries the agent saw, not turn-end loop iterations. Returns the new
883
- * count, or 0 when there is no entry to count against (already retired,
884
- * or never recorded).
885
- */
886
- incrementInlineBlockerStaleDelivery(filePath) {
887
- const key = path.resolve(filePath);
888
- const existing = this._pendingInlineBlockers.get(key);
889
- if (!existing)
890
- return 0;
891
- const next = (existing.staleDeliveryCount ?? 0) + 1;
892
- this._pendingInlineBlockers.set(key, {
893
- ...existing,
894
- staleDeliveryCount: next,
895
- });
896
- return next;
897
- }
898
- /**
899
- * #1950: retire a dependency-drift demotion once it has been delivered
900
- * `DEPENDENCY_DRIFT_MAX_DELIVERIES` times with no re-run confirming or
901
- * clearing it. Unlike {@link retireDemotedPastEofBlocker}, the record is
902
- * NOT provably unrecoverable — its coordinates are still in bounds, and a
903
- * fresh dispatch of the file could still confirm or clear it. This is a
904
- * bounded-noise cap, not a "this can never resolve" verdict, and the
905
- * caller's ledger reason must say so (`demoted-finding-retired`'s "capped,
906
- * re-run can still confirm" vs. past-EOF's "retired, unrecoverable").
907
- *
908
- * Only ever touches this gate's OWN demotion (`staleReason ===
909
- * "dependency-drift"`) — a past-EOF demotion on the same file is that
910
- * gate's own record to retire, not this one's.
911
- *
912
- * @returns true when an entry was retired — the caller records it, so the
913
- * suppression is never silent (#1432 Gap 1).
914
- */
915
- retireDemotedDependencyDriftBlocker(filePath) {
916
- const key = path.resolve(filePath);
917
- const existing = this._pendingInlineBlockers.get(key);
918
- if (!existing)
919
- return false;
920
- if (!existing.stale)
921
- return false;
922
- if (existing.staleReason !== "dependency-drift")
923
- return false;
924
- this._pendingInlineBlockers.delete(key);
925
- return true;
926
- }
927
- /**
928
- * Retire a file's inline blocker because a FRESH, content-bound diagnostic
929
- * verdict proved it gone (#1561).
930
- *
931
- * The map was invalidated by exactly two events: a later dispatch of the
932
- * SAME path returning no blockers, and that path ceasing to exist (#1245).
933
- * Neither covers the common case that produced #1561 — a blocker on file F
934
- * whose cause lives in file G. Fixing G re-dispatches G, not F, so F's
935
- * verdict was never re-taken and "Unresolved from this turn" was re-injected
936
- * for the rest of the session. In the live case the agent then ran
937
- * `lsp_diagnostics` on F, pi-lens answered "confirmed clean", and the
938
- * blocker was STILL re-served on the next three turn ends: #571 wired that
939
- * tool's confirmed result into the widget footer and stopped there.
940
- *
941
- * This is the seam #1198 invariant 4 left undecided, decided: an affirmative
942
- * clean from the authoritative current view retires the stale verdict.
943
- *
944
- * Ordering (#1198 invariants 1-2). Both stores draw from the same
945
- * `nextWriteIndex()` counter, so when both sides are stamped the retire
946
- * requires the clean verdict to be strictly NEWER. A slow old clean that
947
- * settles after a fresh dispatch found real blockers must not erase them.
948
- * When either side is unstamped the two cannot be ordered at all; the fresh
949
- * confirmed verdict wins, because it is the only one of the two backed by an
950
- * actual observation of current content. Only production's single record site
951
- * is stamped, so in practice the unstamped branch is legacy callers/tests.
952
- *
953
- * COVERAGE (#1561 F1). A blocker is retired only by a verdict that can speak
954
- * for the tools that raised it. Inline blockers come from the whole dispatch,
955
- * not just the language server: `dispatcher.ts` collects every
956
- * `semantic === "blocking"` diagnostic across all runners, so eslint,
957
- * biome-check, actionlint, elixir/gleam-check and ast-grep security rules all
958
- * land in this map. A language-server check knows nothing about any of them,
959
- * so `coveredSources` must be a SUPERSET of the recorded sources or the entry
960
- * stands. This is a commit gate: a record whose provenance is unknown (no
961
- * `sources`) fails CLOSED and is never retired, because "we don't know what
962
- * raised this" must not resolve to "an LSP check can clear it".
963
- *
964
- * @returns true when an entry was retired — the caller logs it, so an
965
- * eviction is never silent (#1432 Gap 1).
966
- */
967
- retireInlineBlockerOnConfirmedClean(filePath, confirmedAtWriteIndex, coveredSources) {
968
- const key = path.resolve(filePath);
969
- const existing = this._pendingInlineBlockers.get(key);
970
- if (!existing)
971
- return false;
972
- if (existing.writeIndex !== undefined &&
973
- confirmedAtWriteIndex !== undefined &&
974
- confirmedAtWriteIndex <= existing.writeIndex) {
975
- return false;
976
- }
977
- // Fail closed on unknown provenance, and on any source the fresh verdict
978
- // did not consult. An eslint-origin blocker outliving an LSP-only clean is
979
- // the correct outcome — the next dispatch of that file is what clears it.
980
- if (!existing.sources || existing.sources.length === 0)
981
- return false;
982
- const covered = new Set(coveredSources ?? []);
983
- if (!existing.sources.every((source) => covered.has(source)))
984
- return false;
985
- this._pendingInlineBlockers.delete(key);
986
- return true;
987
- }
988
- reconcileInlineBlockers() {
989
- // Rebuild, never delete-in-place: `PathKeyedMap.delete()` re-normalizes
990
- // the key, and `normalizeMapKey` realpaths a live file but lowercases
991
- // the tail of a deleted one — so on Windows a mixed-case filename gets
992
- // a DIFFERENT delete-time key than its set-time key and the delete
993
- // misses (#1245, verified live: `MyCase.ts` survived reconcile).
994
- // Existence-checking the display path and rebuilding survivors avoids
995
- // the key-mismatch entirely; live survivors re-set to identical keys
996
- // (both realpath), so only the stale entries are dropped.
997
- const survivors = [];
998
- for (const [displayPath, value] of this._pendingInlineBlockers.entries()) {
999
- if (fs.existsSync(displayPath))
1000
- survivors.push([displayPath, value]);
1001
- }
1002
- if (survivors.length !== this._pendingInlineBlockers.size) {
1003
- this._pendingInlineBlockers.clear();
1004
- for (const [displayPath, value] of survivors) {
1005
- this._pendingInlineBlockers.set(displayPath, value);
1006
- }
1007
- }
1008
- }
1009
- /**
1010
- * Stale-entry reconcile (#1245): a blocker recorded for a file that has
1011
- * since been deleted can never be cleared — `clearInlineBlockers` fires
1012
- * only on a LATER dispatch of the same path, which a deleted file never
1013
- * gets. Every read of the blocker map (turn_end injection, git-guard
1014
- * size/summary, `syncGitGuardRecord`) therefore drops entries whose file no
1015
- * longer exists on disk: a blocker for a deleted file is stale by
1016
- * definition (the agent cannot fix it), so it must not re-surface every
1017
- * turn or gate a commit. The map is tiny (per-turn blockers) and reads are
1018
- * bounded (once per turn_end / tool_result), so the probe cost is
1019
- * negligible.
1020
- */
1021
- getInlineBlockersSnapshot() {
1022
- this.reconcileInlineBlockers();
1023
- return [...this._pendingInlineBlockers.values()];
1024
- }
1025
- consumeInlineBlockers() {
1026
- const entries = this.getInlineBlockersSnapshot();
1027
- this._pendingInlineBlockers.clear();
1028
- return entries;
1029
- }
1030
- recordActionableWarnings(warnings) {
1031
- for (const warning of warnings) {
1032
- this._actionableWarningsThisTurn.set(warning.id, warning);
1033
- }
1034
- }
1035
- peekActionableWarnings() {
1036
- return [...this._actionableWarningsThisTurn.values()];
1037
- }
1038
- clearActionableWarnings() {
1039
- this._actionableWarningsThisTurn.clear();
1040
- }
1041
- recordCodeQualityWarnings(warnings) {
1042
- for (const warning of warnings) {
1043
- this._codeQualityWarningsThisTurn.set(warning.id, warning);
1044
- }
1045
- }
1046
- peekCodeQualityWarnings() {
1047
- return [...this._codeQualityWarningsThisTurn.values()];
1048
- }
1049
- clearCodeQualityWarnings() {
1050
- this._codeQualityWarningsThisTurn.clear();
1051
- }
1052
- /** #484: the per-run diagnostics/autofix/format collector (accumulates
1053
- * across turns; consumed once at the agent_settled quiet window). Always
1054
- * present; callers gate recording behind the `lens-turn-summary` opt-in
1055
- * flag. */
1056
- get turnSummary() {
1057
- return this._turnSummary;
1058
- }
1059
- get complexityBaselines() {
1060
- return this._complexityBaselines;
1061
- }
1062
- get fixedThisTurn() {
1063
- // Self-referencing local so chained add() returns the same facade
1064
- // instead of re-entering this getter and allocating a new one per call
1065
- // (sonar S7725).
1066
- const facade = {
1067
- add: (filePath) => {
1068
- this._fixedThisTurn.set(filePath, true);
1069
- return facade;
1070
- },
1071
- has: (filePath) => this._fixedThisTurn.has(filePath),
1072
- delete: (filePath) => this._fixedThisTurn.delete(filePath),
1073
- clear: () => this._fixedThisTurn.clear(),
1074
- };
1075
- return facade;
1076
- }
1077
- get projectRulesScan() {
1078
- return this._projectRulesScan;
1079
- }
1080
- set projectRulesScan(value) {
1081
- this._projectRulesScan = value;
1082
- }
1083
- get readGuard() {
1084
- this._readGuard ??= new ReadGuard(this._telemetrySessionId);
1085
- return this._readGuard;
1086
- }
1087
- /**
1088
- * Record the canonical target `tool_call` resolved for `toolCallId`
1089
- * (#1642). The paired `tool_result` claims this exactly once via
1090
- * {@link takeToolCallAttribution} instead of re-deriving a path from its
1091
- * own diff metadata.
1092
- */
1093
- recordToolCallAttribution(toolCallId, attribution) {
1094
- this._toolCallAttributions.set(toolCallId, {
1095
- ...attribution,
1096
- recordedAt: Date.now(),
1097
- });
1098
- }
1099
- /**
1100
- * One-shot claim of a previously recorded tool-call attribution. Removed
1101
- * on read: a given `tool_call`/`tool_result` pair correlates exactly once,
1102
- * and leaving it behind would let a later, unrelated `tool_result` that
1103
- * happens to reuse a stale id inherit a stranger's resolved path.
1104
- *
1105
- * An expired entry (older than `TOOL_CALL_ATTRIBUTION_TTL_MS`) is treated
1106
- * as a miss and removed rather than returned — see the constant's doc.
1107
- */
1108
- takeToolCallAttribution(toolCallId) {
1109
- const attribution = this._toolCallAttributions.get(toolCallId);
1110
- if (attribution === undefined)
1111
- return undefined;
1112
- this._toolCallAttributions.delete(toolCallId);
1113
- if (Date.now() - attribution.recordedAt > TOOL_CALL_ATTRIBUTION_TTL_MS) {
1114
- return undefined;
1115
- }
1116
- return attribution;
1117
- }
1118
- /**
1119
- * Queue one mutation kind for `filePath` at `agent_end`. Returns `true`
1120
- * when this call created a pending entry or added a new kind, and `false`
1121
- * for a same-kind re-touch. Callers publish each kind's first transition
1122
- * without spamming repeated edits before `agent_end`.
1123
- */
1124
- deferMutation(filePath, cwd,
1125
- /** Host tool name; any mutating tool, not just `write`/`edit` (#2423). */
1126
- toolName, turnStateCwd, kind, ownerSessionId, originCwd) {
1127
- const key = path.resolve(filePath);
1128
- const now = Date.now();
1129
- const resolvedOriginCwd = originCwd ?? turnStateCwd;
1130
- const existing = this._pendingDeferredMutations.get(key);
1131
- if (existing) {
1132
- const addedKind = !existing.kinds.has(kind);
1133
- existing.lastTouchedAt = now;
1134
- existing.cwd = cwd;
1135
- existing.turnStateCwd = turnStateCwd;
1136
- existing.toolNames.add(toolName);
1137
- existing.kinds.add(kind);
1138
- existing.queuedTurnIndex = this._turnIndex;
1139
- existing.queuedTurnId = `${this._telemetrySessionId}:${this._turnIndex}`;
1140
- existing.ownerSessionId = ownerSessionId;
1141
- existing.originCwd = resolvedOriginCwd;
1142
- return addedKind;
1143
- }
1144
- this._pendingDeferredMutations.set(key, {
1145
- filePath: key,
1146
- cwd,
1147
- turnStateCwd,
1148
- firstTouchedAt: now,
1149
- lastTouchedAt: now,
1150
- toolNames: new Set([toolName]),
1151
- kinds: new Set([kind]),
1152
- queuedTurnIndex: this._turnIndex,
1153
- queuedTurnId: `${this._telemetrySessionId}:${this._turnIndex}`,
1154
- ownerSessionId,
1155
- originCwd: resolvedOriginCwd,
1156
- });
1157
- return true;
1158
- }
1159
- deferFormat(filePath, cwd,
1160
- /** Host tool name; any mutating tool, not just `write`/`edit` (#2423). */
1161
- toolName, turnStateCwd, ownerSessionId, originCwd) {
1162
- return this.deferMutation(filePath, cwd, toolName, turnStateCwd, "format", ownerSessionId, originCwd);
1163
- }
1164
- get pendingDeferredFormatCount() {
1165
- return this._pendingDeferredMutations.size;
1166
- }
1167
- get pendingDeferredMutationCount() {
1168
- return this._pendingDeferredMutations.size;
1169
- }
1170
- /**
1171
- * Legacy unconditional drain — still exposed for any caller that
1172
- * genuinely wants "everything, no ownership check" (and for tests). New
1173
- * flush call sites should prefer {@link claimDeferredFormatFiles}.
1174
- */
1175
- consumeDeferredFormatFiles() {
1176
- const records = [...this._pendingDeferredMutations.values()];
1177
- this._pendingDeferredMutations.clear();
1178
- return records;
1179
- }
1180
- /**
1181
- * Ownership-filtered drain (#791). Claims and removes only the records
1182
- * this flush is entitled to:
1183
- * - `ownerSessionId` unset on the record, OR `currentSessionId` unset, OR
1184
- * they match → claimed as "same session" (the common case, and the
1185
- * fail-safe default when either side lacks a stable session id).
1186
- * - otherwise (both known, and they differ) the record belongs to a
1187
- * DIFFERENT session (e.g. a concurrent in-process secondary/subagent)
1188
- * and is left queued for its owner's own flush — UNLESS it has sat
1189
- * unclaimed longer than `staleAfterMs` (the owner presumably died), in
1190
- * which case this flush claims it as an orphan-recovery fallback ONLY
1191
- * when `currentOriginCwd` (this flush's own workspace/worktree) exactly
1192
- * matches the record's `originCwd` (the cwd it was actually queued
1193
- * under, #1642 F3 — NOT `turnStateCwd`, which is always the workspace
1194
- * root by design and so would match every session unconditionally). A
1195
- * mismatch means the record belongs to a DIFFERENT checkout/worktree
1196
- * than the one now running `agent_end` — claiming it across that
1197
- * boundary is exactly how a worktree's queued edit got formatted onto
1198
- * the parent checkout in the reported incident. It is left queued
1199
- * (NOT deleted) and logged instead: a legitimate crashed-session
1200
- * orphan from, say, a monorepo subdir must still be claimable later by
1201
- * a flush whose origin actually matches, or stay visible for
1202
- * observability — deleting it here would drop it forever with no
1203
- * origin ever able to reclaim it.
1204
- *
1205
- * Returns the claimed records, the left-queued mismatched-origin records,
1206
- * and per-skipped record why it was left behind — callers use this for
1207
- * `agent_end`'s latency-log provenance and for the "stale fallback
1208
- * fired"/"orphan mismatch" log lines.
1209
- */
1210
- claimDeferredFormatFiles(currentSessionId, now, staleAfterMs, currentOriginCwd) {
1211
- const claimed = [];
1212
- const staleClaimed = [];
1213
- const deferredToOwner = [];
1214
- const droppedOrphans = [];
1215
- for (const [key, record] of this._pendingDeferredMutations) {
1216
- const sameSession = record.ownerSessionId === undefined ||
1217
- currentSessionId === undefined ||
1218
- record.ownerSessionId === currentSessionId;
1219
- if (sameSession) {
1220
- claimed.push(record);
1221
- this._pendingDeferredMutations.delete(key);
1222
- continue;
1223
- }
1224
- const age = now - record.lastTouchedAt;
1225
- if (age > staleAfterMs) {
1226
- // #1642 F3: origin identity is required before an orphan-recovery
1227
- // claim, not just staleness. `currentOriginCwd === undefined`
1228
- // means the caller can't state its own origin — fail-safe as
1229
- // "can't prove different" (same posture as the sameSession check
1230
- // above), not as a free pass to claim across a KNOWN mismatch.
1231
- const originMatches = currentOriginCwd === undefined ||
1232
- pathsEqual(record.originCwd, currentOriginCwd);
1233
- if (originMatches) {
1234
- this._pendingDeferredMutations.delete(key);
1235
- staleClaimed.push(record);
1236
- }
1237
- else {
1238
- // Left queued — see the doc above for why this must not be
1239
- // deleted. Reported once per claim attempt; a genuinely
1240
- // abandoned origin will keep surfacing here, which is the
1241
- // intended, safer trade-off over silent, permanent loss.
1242
- droppedOrphans.push(record);
1243
- }
1244
- continue;
1245
- }
1246
- deferredToOwner.push(record);
1247
- }
1248
- return { claimed, staleClaimed, deferredToOwner, droppedOrphans };
1249
- }
1250
- /** Return claimed records that were never started by an aborted drain. */
1251
- requeueDeferredFormatFiles(records) {
1252
- for (const record of records) {
1253
- const key = path.resolve(record.filePath);
1254
- const existing = this._pendingDeferredMutations.get(key);
1255
- if (existing) {
1256
- for (const kind of record.kinds)
1257
- existing.kinds.add(kind);
1258
- for (const toolName of record.toolNames)
1259
- existing.toolNames.add(toolName);
1260
- continue;
1261
- }
1262
- this._pendingDeferredMutations.set(key, {
1263
- ...record,
1264
- kinds: new Set(record.kinds),
1265
- toolNames: new Set(record.toolNames),
1266
- });
1267
- }
1268
- }
1269
- claimDeferredMutations(currentSessionId, now, staleAfterMs, currentOriginCwd) {
1270
- return this.claimDeferredFormatFiles(currentSessionId, now, staleAfterMs, currentOriginCwd);
1271
- }
1272
- requeueDeferredMutations(records) {
1273
- this.requeueDeferredFormatFiles(records);
1274
- }
1275
- shouldWarmLspOnRead(filePath, maxAgeMs = 120_000) {
1276
- const state = this._lspReadWarmState.get(path.resolve(filePath));
1277
- if (!state)
1278
- return true;
1279
- if (state.status === "warming")
1280
- return false;
1281
- return Date.now() - state.ts > maxAgeMs;
1282
- }
1283
- markLspReadWarmStarted(filePath) {
1284
- this._lspReadWarmState.set(path.resolve(filePath), {
1285
- status: "warming",
1286
- ts: Date.now(),
1287
- });
1288
- }
1289
- markLspReadWarmCompleted(filePath) {
1290
- this._lspReadWarmState.set(path.resolve(filePath), {
1291
- status: "ready",
1292
- ts: Date.now(),
1293
- });
1294
- }
1295
- clearLspReadWarmState(filePath) {
1296
- this._lspReadWarmState.delete(path.resolve(filePath));
1297
- }
1298
- }
1299
- /**
1300
- * Read the live model identity off a pi extension context (#1655 item 2).
1301
- *
1302
- * `ExtensionContext.model` is `AgentSession.model`, projected through a lazy
1303
- * getter guarded by `assertActive()`
1304
- * (`@earendil-works/pi-coding-agent/dist/core/extensions/runner.js:488-491`;
1305
- * `dist/core/agent-session.js:580-582`). The value is a `Model` with `id` and
1306
- * `provider` (`@earendil-works/pi-ai/dist/types.d.ts:661-667`), or `undefined`
1307
- * when no model is selected.
1308
- *
1309
- * Because the getter is lazy and guarded, reading it on a REPLACED runner
1310
- * throws. Telemetry identity is advisory; a stale ctx must degrade to "no
1311
- * identity", never take down the event handler that happened to carry it.
1312
- */
1313
- export function readHostModelIdentity(ctx) {
1314
- try {
1315
- const model = ctx?.model;
1316
- return {
1317
- model: typeof model?.id === "string" ? model.id : undefined,
1318
- provider: typeof model?.provider === "string" ? model.provider : undefined,
1319
- };
1320
- }
1321
- catch {
1322
- return {};
1323
- }
1324
- }