@memlab/mcp-server 2.18.1 → 2.86.0

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 (374) hide show
  1. package/README.md +30 -16
  2. package/bin/.eslintrc.js +26 -0
  3. package/bin/memlab-cli.js +313 -0
  4. package/dist/anonymized-snapshot.d.ts +75 -0
  5. package/dist/anonymized-snapshot.d.ts.map +1 -0
  6. package/dist/anonymized-snapshot.js +101 -0
  7. package/dist/anonymized-snapshot.js.map +1 -0
  8. package/dist/artifact-classes.d.ts +86 -0
  9. package/dist/artifact-classes.d.ts.map +1 -0
  10. package/dist/artifact-classes.js +261 -0
  11. package/dist/artifact-classes.js.map +1 -0
  12. package/dist/capture-mode.d.ts +60 -0
  13. package/dist/capture-mode.d.ts.map +1 -0
  14. package/dist/capture-mode.js +39 -0
  15. package/dist/capture-mode.js.map +1 -0
  16. package/dist/eval-hints.d.ts +41 -0
  17. package/dist/eval-hints.d.ts.map +1 -0
  18. package/dist/eval-hints.js +115 -0
  19. package/dist/eval-hints.js.map +1 -0
  20. package/dist/guardrail.d.ts.map +1 -1
  21. package/dist/guardrail.js +13 -0
  22. package/dist/guardrail.js.map +1 -1
  23. package/dist/heap-budget.d.ts +32 -0
  24. package/dist/heap-budget.d.ts.map +1 -0
  25. package/dist/heap-budget.js +90 -0
  26. package/dist/heap-budget.js.map +1 -0
  27. package/dist/heap-shapes.d.ts +148 -0
  28. package/dist/heap-shapes.d.ts.map +1 -0
  29. package/dist/heap-shapes.js +193 -0
  30. package/dist/heap-shapes.js.map +1 -0
  31. package/dist/heap-state.d.ts +109 -2
  32. package/dist/heap-state.d.ts.map +1 -1
  33. package/dist/heap-state.js +194 -3
  34. package/dist/heap-state.js.map +1 -1
  35. package/dist/index.js +102 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/progress.d.ts +25 -0
  38. package/dist/progress.d.ts.map +1 -0
  39. package/dist/progress.js +46 -0
  40. package/dist/progress.js.map +1 -0
  41. package/dist/react-shapes.d.ts +42 -0
  42. package/dist/react-shapes.d.ts.map +1 -0
  43. package/dist/react-shapes.js +149 -0
  44. package/dist/react-shapes.js.map +1 -0
  45. package/dist/result-handles.d.ts +11 -0
  46. package/dist/result-handles.d.ts.map +1 -0
  47. package/dist/result-handles.js +77 -0
  48. package/dist/result-handles.js.map +1 -0
  49. package/dist/server-version.d.ts +19 -0
  50. package/dist/server-version.d.ts.map +1 -0
  51. package/dist/server-version.js +19 -0
  52. package/dist/server-version.js.map +1 -0
  53. package/dist/snapshot-borrow.d.ts +67 -0
  54. package/dist/snapshot-borrow.d.ts.map +1 -0
  55. package/dist/snapshot-borrow.js +113 -0
  56. package/dist/snapshot-borrow.js.map +1 -0
  57. package/dist/string-index.d.ts +55 -0
  58. package/dist/string-index.d.ts.map +1 -0
  59. package/dist/string-index.js +99 -0
  60. package/dist/string-index.js.map +1 -0
  61. package/dist/tool-registry.d.ts +42 -0
  62. package/dist/tool-registry.d.ts.map +1 -0
  63. package/dist/tool-registry.js +20 -0
  64. package/dist/tool-registry.js.map +1 -0
  65. package/dist/tools/analyze-run.d.ts +12 -0
  66. package/dist/tools/analyze-run.d.ts.map +1 -0
  67. package/dist/tools/analyze-run.js +404 -0
  68. package/dist/tools/analyze-run.js.map +1 -0
  69. package/dist/tools/anonymize-snapshot.d.ts +12 -0
  70. package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
  71. package/dist/tools/anonymize-snapshot.js +159 -0
  72. package/dist/tools/anonymize-snapshot.js.map +1 -0
  73. package/dist/tools/app-config.d.ts +12 -0
  74. package/dist/tools/app-config.d.ts.map +1 -0
  75. package/dist/tools/app-config.js +217 -0
  76. package/dist/tools/app-config.js.map +1 -0
  77. package/dist/tools/app-heap.d.ts +30 -0
  78. package/dist/tools/app-heap.d.ts.map +1 -0
  79. package/dist/tools/app-heap.js +106 -0
  80. package/dist/tools/app-heap.js.map +1 -0
  81. package/dist/tools/artifact-budget.d.ts +12 -0
  82. package/dist/tools/artifact-budget.d.ts.map +1 -0
  83. package/dist/tools/artifact-budget.js +219 -0
  84. package/dist/tools/artifact-budget.js.map +1 -0
  85. package/dist/tools/async-census.d.ts +12 -0
  86. package/dist/tools/async-census.d.ts.map +1 -0
  87. package/dist/tools/async-census.js +243 -0
  88. package/dist/tools/async-census.js.map +1 -0
  89. package/dist/tools/auto-investigate.d.ts.map +1 -1
  90. package/dist/tools/auto-investigate.js +54 -5
  91. package/dist/tools/auto-investigate.js.map +1 -1
  92. package/dist/tools/batch.d.ts +12 -0
  93. package/dist/tools/batch.d.ts.map +1 -0
  94. package/dist/tools/batch.js +196 -0
  95. package/dist/tools/batch.js.map +1 -0
  96. package/dist/tools/cache-analysis.d.ts +15 -0
  97. package/dist/tools/cache-analysis.d.ts.map +1 -1
  98. package/dist/tools/cache-analysis.js +240 -14
  99. package/dist/tools/cache-analysis.js.map +1 -1
  100. package/dist/tools/census-diff.d.ts +55 -0
  101. package/dist/tools/census-diff.d.ts.map +1 -0
  102. package/dist/tools/census-diff.js +228 -0
  103. package/dist/tools/census-diff.js.map +1 -0
  104. package/dist/tools/chain-walk.d.ts +12 -0
  105. package/dist/tools/chain-walk.d.ts.map +1 -0
  106. package/dist/tools/chain-walk.js +184 -0
  107. package/dist/tools/chain-walk.js.map +1 -0
  108. package/dist/tools/class-histogram.d.ts.map +1 -1
  109. package/dist/tools/class-histogram.js +14 -3
  110. package/dist/tools/class-histogram.js.map +1 -1
  111. package/dist/tools/collection-diff.d.ts +44 -0
  112. package/dist/tools/collection-diff.d.ts.map +1 -0
  113. package/dist/tools/collection-diff.js +343 -0
  114. package/dist/tools/collection-diff.js.map +1 -0
  115. package/dist/tools/collection-trend.d.ts +55 -0
  116. package/dist/tools/collection-trend.d.ts.map +1 -0
  117. package/dist/tools/collection-trend.js +315 -0
  118. package/dist/tools/collection-trend.js.map +1 -0
  119. package/dist/tools/detached-dom.d.ts +5 -0
  120. package/dist/tools/detached-dom.d.ts.map +1 -1
  121. package/dist/tools/detached-dom.js +368 -22
  122. package/dist/tools/detached-dom.js.map +1 -1
  123. package/dist/tools/dev-artifacts.d.ts +62 -6
  124. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  125. package/dist/tools/dev-artifacts.js +685 -24
  126. package/dist/tools/dev-artifacts.js.map +1 -1
  127. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  128. package/dist/tools/diff-snapshots.js +18 -2
  129. package/dist/tools/diff-snapshots.js.map +1 -1
  130. package/dist/tools/dom-audit.d.ts +37 -0
  131. package/dist/tools/dom-audit.d.ts.map +1 -0
  132. package/dist/tools/dom-audit.js +247 -0
  133. package/dist/tools/dom-audit.js.map +1 -0
  134. package/dist/tools/dominator-attribution.d.ts +12 -0
  135. package/dist/tools/dominator-attribution.d.ts.map +1 -0
  136. package/dist/tools/dominator-attribution.js +189 -0
  137. package/dist/tools/dominator-attribution.js.map +1 -0
  138. package/dist/tools/dominator-chain.d.ts +12 -0
  139. package/dist/tools/dominator-chain.d.ts.map +1 -0
  140. package/dist/tools/dominator-chain.js +92 -0
  141. package/dist/tools/dominator-chain.js.map +1 -0
  142. package/dist/tools/duplicate-objects.d.ts +12 -0
  143. package/dist/tools/duplicate-objects.d.ts.map +1 -0
  144. package/dist/tools/duplicate-objects.js +172 -0
  145. package/dist/tools/duplicate-objects.js.map +1 -0
  146. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  147. package/dist/tools/duplicated-strings.js +49 -40
  148. package/dist/tools/duplicated-strings.js.map +1 -1
  149. package/dist/tools/eval-across.d.ts +12 -0
  150. package/dist/tools/eval-across.d.ts.map +1 -0
  151. package/dist/tools/eval-across.js +135 -0
  152. package/dist/tools/eval-across.js.map +1 -0
  153. package/dist/tools/eval.d.ts +79 -0
  154. package/dist/tools/eval.d.ts.map +1 -1
  155. package/dist/tools/eval.js +2523 -197
  156. package/dist/tools/eval.js.map +1 -1
  157. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  158. package/dist/tools/event-listener-leaks.js +42 -17
  159. package/dist/tools/event-listener-leaks.js.map +1 -1
  160. package/dist/tools/event-registry.d.ts.map +1 -1
  161. package/dist/tools/event-registry.js +42 -8
  162. package/dist/tools/event-registry.js.map +1 -1
  163. package/dist/tools/explain-delta.d.ts +12 -0
  164. package/dist/tools/explain-delta.d.ts.map +1 -0
  165. package/dist/tools/explain-delta.js +221 -0
  166. package/dist/tools/explain-delta.js.map +1 -0
  167. package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
  168. package/dist/tools/find-nodes-by-class.js +112 -13
  169. package/dist/tools/find-nodes-by-class.js.map +1 -1
  170. package/dist/tools/finding-index.d.ts +203 -0
  171. package/dist/tools/finding-index.d.ts.map +1 -0
  172. package/dist/tools/finding-index.js +566 -0
  173. package/dist/tools/finding-index.js.map +1 -0
  174. package/dist/tools/for-each.d.ts.map +1 -1
  175. package/dist/tools/for-each.js +15 -3
  176. package/dist/tools/for-each.js.map +1 -1
  177. package/dist/tools/get-referrers.d.ts.map +1 -1
  178. package/dist/tools/get-referrers.js +17 -0
  179. package/dist/tools/get-referrers.js.map +1 -1
  180. package/dist/tools/get-value.d.ts +16 -0
  181. package/dist/tools/get-value.d.ts.map +1 -1
  182. package/dist/tools/get-value.js +96 -2
  183. package/dist/tools/get-value.js.map +1 -1
  184. package/dist/tools/hunt-report.d.ts +12 -0
  185. package/dist/tools/hunt-report.d.ts.map +1 -0
  186. package/dist/tools/hunt-report.js +186 -0
  187. package/dist/tools/hunt-report.js.map +1 -0
  188. package/dist/tools/hypothesis.d.ts +12 -0
  189. package/dist/tools/hypothesis.d.ts.map +1 -0
  190. package/dist/tools/hypothesis.js +280 -0
  191. package/dist/tools/hypothesis.js.map +1 -0
  192. package/dist/tools/id-space-audit.d.ts +12 -0
  193. package/dist/tools/id-space-audit.d.ts.map +1 -0
  194. package/dist/tools/id-space-audit.js +262 -0
  195. package/dist/tools/id-space-audit.js.map +1 -0
  196. package/dist/tools/identify.d.ts +12 -0
  197. package/dist/tools/identify.d.ts.map +1 -0
  198. package/dist/tools/identify.js +205 -0
  199. package/dist/tools/identify.js.map +1 -0
  200. package/dist/tools/identity-diff.d.ts +12 -0
  201. package/dist/tools/identity-diff.d.ts.map +1 -0
  202. package/dist/tools/identity-diff.js +188 -0
  203. package/dist/tools/identity-diff.js.map +1 -0
  204. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  205. package/dist/tools/intern-opportunities.js +116 -50
  206. package/dist/tools/intern-opportunities.js.map +1 -1
  207. package/dist/tools/ladder-probe.d.ts +65 -0
  208. package/dist/tools/ladder-probe.d.ts.map +1 -0
  209. package/dist/tools/ladder-probe.js +445 -0
  210. package/dist/tools/ladder-probe.js.map +1 -0
  211. package/dist/tools/ladder.d.ts +33 -0
  212. package/dist/tools/ladder.d.ts.map +1 -0
  213. package/dist/tools/ladder.js +266 -0
  214. package/dist/tools/ladder.js.map +1 -0
  215. package/dist/tools/largest-objects.d.ts.map +1 -1
  216. package/dist/tools/largest-objects.js +6 -2
  217. package/dist/tools/largest-objects.js.map +1 -1
  218. package/dist/tools/leak-report.d.ts +35 -0
  219. package/dist/tools/leak-report.d.ts.map +1 -0
  220. package/dist/tools/leak-report.js +398 -0
  221. package/dist/tools/leak-report.js.map +1 -0
  222. package/dist/tools/load-snapshot.d.ts +29 -0
  223. package/dist/tools/load-snapshot.d.ts.map +1 -1
  224. package/dist/tools/load-snapshot.js +294 -23
  225. package/dist/tools/load-snapshot.js.map +1 -1
  226. package/dist/tools/map-entries.d.ts +12 -0
  227. package/dist/tools/map-entries.d.ts.map +1 -0
  228. package/dist/tools/map-entries.js +139 -0
  229. package/dist/tools/map-entries.js.map +1 -0
  230. package/dist/tools/match-object.d.ts +12 -0
  231. package/dist/tools/match-object.d.ts.map +1 -0
  232. package/dist/tools/match-object.js +165 -0
  233. package/dist/tools/match-object.js.map +1 -0
  234. package/dist/tools/metric.d.ts +13 -0
  235. package/dist/tools/metric.d.ts.map +1 -0
  236. package/dist/tools/metric.js +185 -0
  237. package/dist/tools/metric.js.map +1 -0
  238. package/dist/tools/module-attribution.d.ts +36 -0
  239. package/dist/tools/module-attribution.d.ts.map +1 -0
  240. package/dist/tools/module-attribution.js +235 -0
  241. package/dist/tools/module-attribution.js.map +1 -0
  242. package/dist/tools/next-measurement.d.ts +26 -0
  243. package/dist/tools/next-measurement.d.ts.map +1 -0
  244. package/dist/tools/next-measurement.js +149 -0
  245. package/dist/tools/next-measurement.js.map +1 -0
  246. package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
  247. package/dist/tools/object-cost-breakdown.js +64 -0
  248. package/dist/tools/object-cost-breakdown.js.map +1 -1
  249. package/dist/tools/object-shape.d.ts.map +1 -1
  250. package/dist/tools/object-shape.js +53 -5
  251. package/dist/tools/object-shape.js.map +1 -1
  252. package/dist/tools/population-diff.d.ts +57 -0
  253. package/dist/tools/population-diff.d.ts.map +1 -0
  254. package/dist/tools/population-diff.js +338 -0
  255. package/dist/tools/population-diff.js.map +1 -0
  256. package/dist/tools/population-vs-owners.d.ts +12 -0
  257. package/dist/tools/population-vs-owners.d.ts.map +1 -0
  258. package/dist/tools/population-vs-owners.js +183 -0
  259. package/dist/tools/population-vs-owners.js.map +1 -0
  260. package/dist/tools/property-names.d.ts +29 -0
  261. package/dist/tools/property-names.d.ts.map +1 -0
  262. package/dist/tools/property-names.js +131 -0
  263. package/dist/tools/property-names.js.map +1 -0
  264. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  265. package/dist/tools/quick-diagnosis.js +7 -1
  266. package/dist/tools/quick-diagnosis.js.map +1 -1
  267. package/dist/tools/react-owners.d.ts +12 -0
  268. package/dist/tools/react-owners.d.ts.map +1 -0
  269. package/dist/tools/react-owners.js +167 -0
  270. package/dist/tools/react-owners.js.map +1 -0
  271. package/dist/tools/react-update-queues.d.ts +12 -0
  272. package/dist/tools/react-update-queues.d.ts.map +1 -0
  273. package/dist/tools/react-update-queues.js +173 -0
  274. package/dist/tools/react-update-queues.js.map +1 -0
  275. package/dist/tools/replicate.d.ts +49 -0
  276. package/dist/tools/replicate.d.ts.map +1 -0
  277. package/dist/tools/replicate.js +241 -0
  278. package/dist/tools/replicate.js.map +1 -0
  279. package/dist/tools/retainer-diff.d.ts +12 -0
  280. package/dist/tools/retainer-diff.d.ts.map +1 -0
  281. package/dist/tools/retainer-diff.js +168 -0
  282. package/dist/tools/retainer-diff.js.map +1 -0
  283. package/dist/tools/retainer-layers.d.ts +23 -0
  284. package/dist/tools/retainer-layers.d.ts.map +1 -0
  285. package/dist/tools/retainer-layers.js +179 -0
  286. package/dist/tools/retainer-layers.js.map +1 -0
  287. package/dist/tools/retainer-summary.d.ts +18 -0
  288. package/dist/tools/retainer-summary.d.ts.map +1 -1
  289. package/dist/tools/retainer-summary.js +210 -51
  290. package/dist/tools/retainer-summary.js.map +1 -1
  291. package/dist/tools/retainer-trace.d.ts.map +1 -1
  292. package/dist/tools/retainer-trace.js +14 -2
  293. package/dist/tools/retainer-trace.js.map +1 -1
  294. package/dist/tools/round-audit.d.ts +66 -0
  295. package/dist/tools/round-audit.d.ts.map +1 -0
  296. package/dist/tools/round-audit.js +258 -0
  297. package/dist/tools/round-audit.js.map +1 -0
  298. package/dist/tools/round-digest.d.ts +12 -0
  299. package/dist/tools/round-digest.d.ts.map +1 -0
  300. package/dist/tools/round-digest.js +190 -0
  301. package/dist/tools/round-digest.js.map +1 -0
  302. package/dist/tools/script-census.d.ts +12 -0
  303. package/dist/tools/script-census.d.ts.map +1 -0
  304. package/dist/tools/script-census.js +182 -0
  305. package/dist/tools/script-census.js.map +1 -0
  306. package/dist/tools/search-nodes.d.ts.map +1 -1
  307. package/dist/tools/search-nodes.js +5 -1
  308. package/dist/tools/search-nodes.js.map +1 -1
  309. package/dist/tools/search-strings.d.ts.map +1 -1
  310. package/dist/tools/search-strings.js +53 -7
  311. package/dist/tools/search-strings.js.map +1 -1
  312. package/dist/tools/sequence-analysis.d.ts +53 -0
  313. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  314. package/dist/tools/sequence-analysis.js +313 -89
  315. package/dist/tools/sequence-analysis.js.map +1 -1
  316. package/dist/tools/server-status.d.ts.map +1 -1
  317. package/dist/tools/server-status.js +4 -1
  318. package/dist/tools/server-status.js.map +1 -1
  319. package/dist/tools/settle-check.d.ts +12 -0
  320. package/dist/tools/settle-check.d.ts.map +1 -0
  321. package/dist/tools/settle-check.js +188 -0
  322. package/dist/tools/settle-check.js.map +1 -0
  323. package/dist/tools/shape-histogram.d.ts.map +1 -1
  324. package/dist/tools/shape-histogram.js +9 -2
  325. package/dist/tools/shape-histogram.js.map +1 -1
  326. package/dist/tools/sliced-strings.d.ts.map +1 -1
  327. package/dist/tools/sliced-strings.js +2 -1
  328. package/dist/tools/sliced-strings.js.map +1 -1
  329. package/dist/tools/snapshots.d.ts.map +1 -1
  330. package/dist/tools/snapshots.js +24 -6
  331. package/dist/tools/snapshots.js.map +1 -1
  332. package/dist/tools/sparse-elements.d.ts +12 -0
  333. package/dist/tools/sparse-elements.d.ts.map +1 -0
  334. package/dist/tools/sparse-elements.js +215 -0
  335. package/dist/tools/sparse-elements.js.map +1 -0
  336. package/dist/tools/stale-collections.d.ts +17 -0
  337. package/dist/tools/stale-collections.d.ts.map +1 -1
  338. package/dist/tools/stale-collections.js +28 -0
  339. package/dist/tools/stale-collections.js.map +1 -1
  340. package/dist/tools/string-patterns.d.ts.map +1 -1
  341. package/dist/tools/string-patterns.js +7 -5
  342. package/dist/tools/string-patterns.js.map +1 -1
  343. package/dist/tools/tools-index.d.ts +12 -0
  344. package/dist/tools/tools-index.d.ts.map +1 -0
  345. package/dist/tools/tools-index.js +492 -0
  346. package/dist/tools/tools-index.js.map +1 -0
  347. package/dist/tools/trace-all.d.ts +42 -0
  348. package/dist/tools/trace-all.d.ts.map +1 -0
  349. package/dist/tools/trace-all.js +263 -0
  350. package/dist/tools/trace-all.js.map +1 -0
  351. package/dist/tools/unit-cost.d.ts +12 -0
  352. package/dist/tools/unit-cost.d.ts.map +1 -0
  353. package/dist/tools/unit-cost.js +219 -0
  354. package/dist/tools/unit-cost.js.map +1 -0
  355. package/dist/tools/verify-fix.d.ts +23 -0
  356. package/dist/tools/verify-fix.d.ts.map +1 -0
  357. package/dist/tools/verify-fix.js +219 -0
  358. package/dist/tools/verify-fix.js.map +1 -0
  359. package/dist/tools/weakmap-entries.d.ts.map +1 -1
  360. package/dist/tools/weakmap-entries.js +6 -1
  361. package/dist/tools/weakmap-entries.js.map +1 -1
  362. package/dist/tools/weakref-census.d.ts +15 -0
  363. package/dist/tools/weakref-census.d.ts.map +1 -0
  364. package/dist/tools/weakref-census.js +147 -0
  365. package/dist/tools/weakref-census.js.map +1 -0
  366. package/dist/tools/what-if.d.ts +12 -0
  367. package/dist/tools/what-if.d.ts.map +1 -0
  368. package/dist/tools/what-if.js +285 -0
  369. package/dist/tools/what-if.js.map +1 -0
  370. package/dist/utils.d.ts +238 -3
  371. package/dist/utils.d.ts.map +1 -1
  372. package/dist/utils.js +507 -15
  373. package/dist/utils.js.map +1 -1
  374. package/package.json +7 -6
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import memlabCore from '@memlab/core';
11
+ import { z } from 'zod';
12
+ import { getSnapshot, getSnapshotMetadata } from '../heap-state.js';
13
+ import { boundedDominatorRetainedSize, errorResult, formatBytes, formatNumber, markdownTable, toolResult, } from '../utils.js';
14
+ const { NumericSet } = memlabCore;
15
+ function matchesShape(node, shape) {
16
+ const want = new Set(shape);
17
+ for (const e of node.references) {
18
+ if (e.type !== 'property')
19
+ continue;
20
+ want.delete(String(e.name_or_index));
21
+ if (want.size === 0)
22
+ return true;
23
+ }
24
+ return false;
25
+ }
26
+ /**
27
+ * Second-order collectability: what ELSE dies when this population goes away.
28
+ *
29
+ * The dominator-deduped figure is a floor by construction — it counts only what
30
+ * the population exclusively dominates. An object reachable by two paths, both
31
+ * of which run through the population, is dominated by neither member and so is
32
+ * counted by neither, yet it becomes garbage the moment they do. On a graph with
33
+ * shared substructure that is not a rounding error.
34
+ *
35
+ * Answering it properly means recomputing reachability, which is what this does:
36
+ * a BFS from the GC roots with the population's edges removed, compared against
37
+ * the same BFS with them present. It is O(N+E) twice rather than a dominator
38
+ * pass, so it is affordable, but it is a real graph walk and not a heuristic.
39
+ */
40
+ function findRootIds(snapshot) {
41
+ const roots = [];
42
+ snapshot.nodes.forEach(node => {
43
+ if (roots.length > 0)
44
+ return;
45
+ if (node.type === 'synthetic' && node.name.includes('GC roots')) {
46
+ roots.push(node.id);
47
+ }
48
+ });
49
+ if (roots.length === 0) {
50
+ // Fall back to every node V8 marks as unreachable-from-nothing: the first
51
+ // node in a V8 snapshot is the root by convention.
52
+ snapshot.nodes.forEach(node => {
53
+ if (roots.length === 0)
54
+ roots.push(node.id);
55
+ });
56
+ }
57
+ return roots;
58
+ }
59
+ /**
60
+ * Reachability marking uses a flat byte array indexed by node id, not a Set.
61
+ * A Set of ids throws "Set maximum size exceeded" on a large server heap
62
+ * (observed on a 9.9M-node Node.js capture), and the failure lands in the
63
+ * middle of an otherwise-complete analysis. The array costs one byte per id
64
+ * slot — tens of MB on the largest heaps that load at all — and cannot hit a
65
+ * collection limit.
66
+ */
67
+ function maxNodeId(snapshot) {
68
+ let max = 0;
69
+ snapshot.nodes.forEach(node => {
70
+ if (node.id > max)
71
+ max = node.id;
72
+ });
73
+ return max;
74
+ }
75
+ function reachableFrom(snapshot, rootIds, removed, maxId) {
76
+ const seen = new Uint8Array(maxId + 1);
77
+ const stack = [];
78
+ for (const id of rootIds) {
79
+ if (id > maxId || removed[id] === 1)
80
+ continue;
81
+ seen[id] = 1;
82
+ stack.push(id);
83
+ }
84
+ while (stack.length > 0) {
85
+ const id = stack.pop();
86
+ const node = snapshot.getNodeById(id);
87
+ if (node == null)
88
+ continue;
89
+ for (const edge of node.references) {
90
+ // A weak edge does not keep its target alive, so following it would
91
+ // report objects as surviving that a real GC would collect.
92
+ if (edge.type === 'weak')
93
+ continue;
94
+ const toId = edge.toNode.id;
95
+ if (toId > maxId || removed[toId] === 1 || seen[toId] === 1)
96
+ continue;
97
+ seen[toId] = 1;
98
+ stack.push(toId);
99
+ }
100
+ }
101
+ return seen;
102
+ }
103
+ export function registerWhatIf(server) {
104
+ server.tool('memlab_what_if', 'If this set of objects were freed, how many bytes would actually come back? Reports the dominator-deduped retained size of a population — the bytes that go away when it does, with nothing double-counted and nothing counted that is also reachable another way.\n\n' +
105
+ 'This is the number every fix decision needs and the one that is easiest to get wrong by hand. Summing per-object retained sizes double-counts every nested object; quoting the class total counts memory that other live code still holds; quoting a container\'s retained size includes internals that survive. `memlab_detached_dom` already reports it for detached subtrees as "Owner Frees" — this makes the same question askable about any set.\n\n' +
106
+ 'Specify the population by ids, class name, or property shape.', {
107
+ node_ids: z
108
+ .array(z.number())
109
+ .optional()
110
+ .describe('Explicit node ids to free (from any tool that reports ids).'),
111
+ class_name: z
112
+ .string()
113
+ .optional()
114
+ .describe('Free every instance of this class (exact name match).'),
115
+ shape: z
116
+ .array(z.string())
117
+ .optional()
118
+ .describe('Free every object carrying ALL of these properties — the usable selector on a minified heap.'),
119
+ breakdown: z
120
+ .boolean()
121
+ .optional()
122
+ .default(true)
123
+ .describe('Also report what the freed bytes consist of, grouped by the class of the dominated nodes (default true). Answers "am I freeing the records, or the data they point at?".'),
124
+ limit: z
125
+ .number()
126
+ .optional()
127
+ .default(12)
128
+ .describe('Rows in the breakdown table (default 12).'),
129
+ cascade: z
130
+ .boolean()
131
+ .optional()
132
+ .default(false)
133
+ .describe('Also compute the SECOND-ORDER effect: objects that become unreachable because the population was their last live referrer, even though no member dominated them. Recomputes reachability from the GC roots with the population removed (two O(N+E) walks — seconds on a multi-million-node heap, not instant). Off by default because the dominator figure alone is the conservative answer.'),
134
+ }, async ({ node_ids, class_name, shape, breakdown, limit, cascade }) => {
135
+ try {
136
+ const snapshot = getSnapshot();
137
+ const selectors = [
138
+ node_ids != null && node_ids.length > 0,
139
+ class_name != null,
140
+ shape != null && shape.length > 0,
141
+ ].filter(Boolean).length;
142
+ if (selectors === 0) {
143
+ return errorResult(new Error('Pass node_ids, class_name or shape to select what to free.'));
144
+ }
145
+ if (selectors > 1) {
146
+ return errorResult(new Error('Pass exactly one of node_ids / class_name / shape — combining them would make the reported population ambiguous.'));
147
+ }
148
+ const ids = [];
149
+ if (node_ids != null && node_ids.length > 0) {
150
+ for (const id of node_ids) {
151
+ if (snapshot.getNodeById(id) != null)
152
+ ids.push(id);
153
+ }
154
+ if (ids.length === 0) {
155
+ return errorResult(new Error('None of those ids exist in the active snapshot. Node ids are per-capture — check the handle with memlab_snapshots.'));
156
+ }
157
+ }
158
+ else {
159
+ snapshot.nodes.forEach(node => {
160
+ if (node.id <= 3)
161
+ return;
162
+ if (class_name != null) {
163
+ if (node.name !== class_name)
164
+ return;
165
+ }
166
+ else if (shape != null && !matchesShape(node, shape)) {
167
+ return;
168
+ }
169
+ ids.push(node.id);
170
+ });
171
+ }
172
+ if (ids.length === 0) {
173
+ return toolResult(`Nothing matched, so there is nothing to free. Check the class name with \`memlab_class_histogram\` or the shape with \`memlab_shape_histogram\`.`);
174
+ }
175
+ const idSet = new NumericSet(ids);
176
+ const { retained, exact } = boundedDominatorRetainedSize(idSet, snapshot);
177
+ const meta = getSnapshotMetadata();
178
+ const heapTotal = meta?.totalSize ?? 0;
179
+ const share = heapTotal > 0 ? (retained / heapTotal) * 100 : 0;
180
+ let selfTotal = 0;
181
+ for (const id of ids) {
182
+ selfTotal += snapshot.getNodeById(id)?.self_size ?? 0;
183
+ }
184
+ const label = class_name != null
185
+ ? `class \`${class_name}\``
186
+ : shape != null
187
+ ? `shape \`{${shape.join(', ')}}\``
188
+ : `${formatNumber(ids.length)} explicit id(s)`;
189
+ const lines = [
190
+ `## What if ${label} were freed?`,
191
+ '',
192
+ `**${formatBytes(retained)} would be reclaimed**${exact ? '' : ' (upper bound — the dominator walk hit its depth cap)'}` +
193
+ `${heapTotal > 0 ? `, ${share.toFixed(1)}% of the ${formatBytes(heapTotal)} heap` : ''}.`,
194
+ '',
195
+ `- Population: ${formatNumber(ids.length)} object(s)`,
196
+ `- Their own bytes (self size): ${formatBytes(selfTotal)}`,
197
+ `- Everything they exclusively dominate: ${formatBytes(retained)}`,
198
+ '',
199
+ retained > selfTotal * 2
200
+ ? `Most of the win is in what these objects HOLD, not in the objects themselves (${formatBytes(retained - selfTotal)} of the total). Freeing them is worth it only if nothing else references that payload — which is exactly what dominator-deduped means, so this figure already accounts for it.`
201
+ : "Nearly all of the win is the objects' own bytes; they hold little exclusively.",
202
+ ];
203
+ if (breakdown) {
204
+ // What the reclaimed bytes actually consist of. "Freeing 26 MB" reads
205
+ // very differently once you know 90% of it is one payload class.
206
+ const byClass = new Map();
207
+ const seen = new Set();
208
+ for (const id of ids) {
209
+ const start = snapshot.getNodeById(id);
210
+ if (start == null)
211
+ continue;
212
+ const stack = [start];
213
+ while (stack.length > 0) {
214
+ const n = stack.pop();
215
+ if (seen.has(n.id))
216
+ continue;
217
+ seen.add(n.id);
218
+ const key = `${n.name} (${n.type})`;
219
+ const e = byClass.get(key) ?? { count: 0, bytes: 0 };
220
+ e.count++;
221
+ e.bytes += n.self_size;
222
+ byClass.set(key, e);
223
+ for (const edge of n.references) {
224
+ const child = edge.toNode;
225
+ if (child.id > 3 &&
226
+ !seen.has(child.id) &&
227
+ child.dominatorNode?.id === n.id) {
228
+ stack.push(child);
229
+ }
230
+ }
231
+ }
232
+ }
233
+ const rows = [...byClass.entries()]
234
+ .sort((a, b) => b[1].bytes - a[1].bytes)
235
+ .slice(0, limit)
236
+ .map(([name, e]) => [
237
+ name.length > 50 ? name.slice(0, 47) + '…' : name,
238
+ formatNumber(e.count),
239
+ formatBytes(e.bytes),
240
+ ]);
241
+ lines.push('', '### What the reclaimed bytes are', '', markdownTable(['Class', 'Nodes', 'Self size'], rows, new Set([1, 2])));
242
+ }
243
+ if (cascade) {
244
+ const maxId = maxNodeId(snapshot);
245
+ const removed = new Uint8Array(maxId + 1);
246
+ for (const id of ids)
247
+ if (id <= maxId)
248
+ removed[id] = 1;
249
+ const none = new Uint8Array(maxId + 1);
250
+ const roots = findRootIds(snapshot);
251
+ const before = reachableFrom(snapshot, roots, none, maxId);
252
+ const after = reachableFrom(snapshot, roots, removed, maxId);
253
+ let cascadeBytes = 0;
254
+ let cascadeNodes = 0;
255
+ for (let id = 0; id <= maxId; id++) {
256
+ if (before[id] !== 1)
257
+ continue;
258
+ // The population's own bytes are already counted; this walk is
259
+ // about what ELSE dies with it.
260
+ if (after[id] === 1 || removed[id] === 1)
261
+ continue;
262
+ cascadeNodes++;
263
+ cascadeBytes += snapshot.getNodeById(id)?.self_size ?? 0;
264
+ }
265
+ // The dominator figure splits into the population's own bytes plus
266
+ // what it exclusively dominates. Only the second part is comparable
267
+ // to the cascade walk, which excludes the population itself.
268
+ const dominatedNonSelf = Math.max(0, retained - selfTotal);
269
+ const extra = cascadeBytes - dominatedNonSelf;
270
+ const totalFreed = selfTotal + cascadeBytes;
271
+ lines.push('', '### Second-order effect (cascade)', '', `Recomputing reachability from ${formatNumber(roots.length)} GC root(s) with this population removed: **${formatNumber(cascadeNodes)} node(s) outside the population / ${formatBytes(cascadeBytes)} become unreachable**, against ${formatBytes(dominatedNonSelf)} that the population exclusively dominates.`, '', extra > 0
272
+ ? `**${formatBytes(extra)} of that is second-order** — objects no member dominated (they were reachable by several paths, all of which ran through the population) but which nothing else keeps alive. Total freed including the population's own ${formatBytes(selfTotal)}: **${formatBytes(totalFreed)}**, against the ${formatBytes(retained)} dominator figure.`
273
+ : extra === 0
274
+ ? 'No second-order effect: the exclusively-dominated set is exactly what becomes unreachable.'
275
+ : `The cascade walk found ${formatBytes(-extra)} LESS than the dominator figure claims is exclusively dominated. That is a discrepancy, not a saving — it means part of the dominated set stays reachable in this walk, most likely through an edge type the walk skips (weak) or a root the walk did not start from (${formatNumber(roots.length)} found). Trust the dominator figure and treat this cascade run as inconclusive.`, '', '_Reachability only. It does not model finalizers, and it treats weak edges as non-retaining (which is correct for collectability but means a WeakMap value shown as freed is freed only if its key also dies)._');
276
+ }
277
+ lines.push('', '_Counts only what this population EXCLUSIVELY dominates: anything also reachable from elsewhere stays and is not included. Second-order effects — objects that become collectable because a freed one was their last referrer without dominating them — are not in this figure, so treat it as a floor; pass `cascade: true` to measure them._');
278
+ return toolResult(lines.join('\n'));
279
+ }
280
+ catch (err) {
281
+ return errorResult(err);
282
+ }
283
+ });
284
+ }
285
+ //# sourceMappingURL=what-if.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"what-if.js","sourceRoot":"","sources":["../../src/tools/what-if.ts"],"names":[],"mappings":"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"}
package/dist/utils.d.ts CHANGED
@@ -40,12 +40,26 @@ export interface IncomingEdge extends EdgeSummary {
40
40
  from_node: NodeSummary;
41
41
  }
42
42
  export declare function truncateDomToTag(name: string): string;
43
+ export declare const BLINK_TEMPLATE_ELISION = "<\u2026>";
44
+ export declare function abbreviateBlinkTypeName(name: string): string;
43
45
  export declare function truncateNodeName(name: string, type: string, selfSize: number, maxLen?: number, aggressiveDom?: boolean): string;
44
46
  export declare function serializeNodeSummary(node: IHeapNode): NodeSummary;
45
47
  export declare function serializeNodeDetail(node: IHeapNode): NodeDetail;
46
48
  export declare function serializeOutgoingEdge(edge: IHeapEdge): OutgoingEdge;
47
49
  export declare function serializeIncomingEdge(edge: IHeapEdge): IncomingEdge;
48
- export declare function isNodeWorthInspecting(node: IHeapNode): boolean;
50
+ /**
51
+ * Whether a node is worth showing in a default "interesting objects" listing.
52
+ *
53
+ * `NODE_TYPE_BLOCK_LIST` exists to keep noise out of the DEFAULT view — it is not
54
+ * meant to make those types unreachable. When a caller explicitly asks for one
55
+ * of them (e.g. `largest_objects({node_type: 'array'})`), honour the request:
56
+ * otherwise the filter silently returns zero rows for `array`, `native`, `code`,
57
+ * `synthetic` and `hidden`, which reads as "there are none" on a heap that
58
+ * plainly contains 100k+ of them.
59
+ */
60
+ export declare function isNodeWorthInspecting(node: IHeapNode, opts?: {
61
+ allowBlockedTypes?: boolean;
62
+ }): boolean;
49
63
  /**
50
64
  * Property names that mark a "freshness" timestamp on a TTL/warm cache wrapper
51
65
  * object (e.g. `{entries, loadedAt}`, `{items, timestamp}`). Their presence next
@@ -71,6 +85,21 @@ export declare function hasFreshnessTimestampSibling(node: IHeapNode): boolean;
71
85
  */
72
86
  export declare function looksLikeFailurePayload(value: string): boolean;
73
87
  export declare function filterLargestObjects(snapshot: IHeapSnapshot, filter: (node: IHeapNode) => boolean, limit: number): IHeapNode[];
88
+ /**
89
+ * As `filterLargestObjects`, but also reports how many nodes MATCHED.
90
+ *
91
+ * The population size is not a nicety. A conclusion drawn from the top 5 of a
92
+ * matching population reads identically whether that population was 5 or 23,918,
93
+ * and the difference decides whether the conclusion is sound: one report stated
94
+ * "all 5 sampled instances share the same retainer pattern — likely a single
95
+ * root cause" where a full-population trace found 1,468 distinct paths, the
96
+ * largest covering 2.2%. The sample fraction has to reach the caller, so the
97
+ * walk that already visits every node returns it.
98
+ */
99
+ export declare function filterLargestObjectsCounted(snapshot: IHeapSnapshot, filter: (node: IHeapNode) => boolean, limit: number): {
100
+ nodes: IHeapNode[];
101
+ matched: number;
102
+ };
74
103
  /**
75
104
  * Collapse heap nodes that are merely different VIEWS of the same dominator
76
105
  * subtree (e.g. on a single in-flight request: Client → Request → closure →
@@ -128,6 +157,85 @@ export declare function boundedDominatorRetainedSize(ids: HeapNodeIdSet, snapsho
128
157
  retained: number;
129
158
  exact: boolean;
130
159
  };
160
+ /**
161
+ * One backing-store slot of a Map/Set/WeakMap: its true FixedArray index
162
+ * (`name_or_index`) and the heap node it points at.
163
+ */
164
+ export interface BackingSlot {
165
+ idx: number;
166
+ node: IHeapNode;
167
+ }
168
+ /**
169
+ * One enumerated Map/WeakMap entry. `value` is null when the value slot held an
170
+ * inline SMI (no heap edge) — see `enumerateMapEntries`.
171
+ */
172
+ export interface CollectionEntry {
173
+ key: IHeapNode;
174
+ value: IHeapNode | null;
175
+ }
176
+ /**
177
+ * Collect the object-valued slots of a Map/Set/WeakMap backing store, sorted by
178
+ * their true FixedArray slot index.
179
+ *
180
+ * V8 stores entries in an OrderedHashMap/OrderedHashSet reachable via the
181
+ * `table` (or `backing_store`) edge. Browser (Chromium) snapshots type the
182
+ * key/value slot edges as `internal` with a numeric name (the array index);
183
+ * Node snapshots type them `element`. The header counts and hash-chain links are
184
+ * inline SMIs, which emit NO edge at all — so the slot indices are NOT
185
+ * contiguous, and the GAPS are meaningful (they mark SMI-valued or deleted
186
+ * slots). Returning the slots WITH their indices lets callers pair by index
187
+ * instead of by position, which is what makes the pairing correct when some
188
+ * values are SMIs (see `enumerateMapEntries`).
189
+ */
190
+ export declare function collectBackingSlots(node: IHeapNode): BackingSlot[];
191
+ /**
192
+ * Enumerate a Map/WeakMap's (key, value) entries.
193
+ *
194
+ * V8 lays each entry out as consecutive slots `[key, value, chain]` (the chain
195
+ * link is an inline SMI, so it emits no edge). We therefore pair a key with the
196
+ * value in the immediately-following slot INDEX (`key.idx + 1`). When no slot
197
+ * exists at `key.idx + 1`, the value was an inline SMI/primitive and we emit
198
+ * `value: null` — instead of mispairing the key with the NEXT entry's key, which
199
+ * is what naive "consecutive object edges = key,value" pairing does whenever a
200
+ * Map has SMI values (a real correctness bug on browser heaps).
201
+ */
202
+ export declare function enumerateMapEntries(node: IHeapNode): CollectionEntry[];
203
+ /** Enumerate a Set's elements (every occupied backing-store slot). */
204
+ export declare function enumerateSetElements(node: IHeapNode): IHeapNode[];
205
+ /**
206
+ * Property names that identify an individual record rather than describe its
207
+ * content — always unique per instance, so INCLUDING them in a content
208
+ * signature defeats duplicate detection (every record looks distinct). Excluded
209
+ * by default from `objectContentSignature`. `id`/`__id`/`__ref` are Relay/GraphQL
210
+ * data-id fields; `key`/`clientMutationId` are common per-instance keys.
211
+ */
212
+ export declare const IDENTITY_PROPS: ReadonlySet<string>;
213
+ /**
214
+ * A stable, shallow content signature for an object: the sorted set of property
215
+ * names, each annotated with its scalar value (strings capped) or a marker for
216
+ * object/array-valued properties. Two objects with the same signature are
217
+ * structurally identical at one level — the basis for duplicate-record
218
+ * detection (`memlab_duplicate_objects`) and ad-hoc dedup checks in eval.
219
+ *
220
+ * By default per-instance identity fields (`IDENTITY_PROPS`: id/__id/__ref/…) are
221
+ * EXCLUDED so records that differ only by their data-id still collapse together
222
+ * — pass `ignoreProps` to override the set (e.g. `new Set()` to include them).
223
+ *
224
+ * String, boolean, null and object-valued properties are captured (objects
225
+ * generically as `o`, so nested content is not compared).
226
+ *
227
+ * Caveat — numeric values are NOT captured: the V8 heap-snapshot format does not
228
+ * store the actual value of a number field (SMI nodes are `smi number`,
229
+ * heap-numbers are `heap number` — the IEEE-754/int value is not accessible; see
230
+ * `tools/get-value.ts`). A numeric property therefore contributes only a generic
231
+ * `<name>=n` marker, so two objects differing ONLY in a numeric field hash to the
232
+ * same signature and are reported as duplicates. Treat numeric-heavy records
233
+ * accordingly (or compare their values via another tool).
234
+ */
235
+ export declare function objectContentSignature(node: IHeapNode, opts?: {
236
+ maxStringLen?: number;
237
+ ignoreProps?: ReadonlySet<string>;
238
+ }): string;
131
239
  /**
132
240
  * Best-effort detection of which app a Node snapshot came from, by tallying the
133
241
  * `/app(s)/<name>/` segment in bundle paths embedded throughout the heap (string
@@ -149,6 +257,54 @@ export declare function instrumentationRetainerNote(steps: Array<{
149
257
  name: string;
150
258
  edgeName?: string;
151
259
  }>): string | null;
260
+ /**
261
+ * The nearest owner reachable by a NAMED property, plus HOW the target hangs
262
+ * off it. `Owner.prop` alone is not an address — the anchor is frequently an
263
+ * ancestor, and reading it as the object's own location is wrong for a large
264
+ * fraction of a real heap.
265
+ *
266
+ * Measured over 3,009 candidate objects on one browser capture: 1,815 hung
267
+ * directly off a named property, 1,084 were entries inside a Map or array, and
268
+ * 105 were variables captured in a closure. For the closure cases the bare
269
+ * anchor also DISCARDED the local variable name — `EMOJI_LIST`,
270
+ * `fbTop50Emojis`, `specialTags` were each reported under an unrelated
271
+ * sibling's property name, which is the single most greppable thing about them.
272
+ *
273
+ * Grouping by the immediate referrer edge does not work either: objects held in
274
+ * a Map are keyed by a numeric slot index in the backing table, so 552
275
+ * identical objects fragment into 552 groups of one. And in a minified bundle
276
+ * the class name is `Object` for all of them.
277
+ */
278
+ export interface NamedOwner {
279
+ /** `<OwnerClass>.<property>` — the greppable part. */
280
+ anchor: string;
281
+ /**
282
+ * `null` when the anchor IS the target's own property slot; otherwise how the
283
+ * target sits under it (`entry`, `closure var caches`, ...).
284
+ */
285
+ relation: string | null;
286
+ /** `anchor`, or `anchor ▸ relation` — what to show a reader. */
287
+ label: string;
288
+ ownerNode: IHeapNode;
289
+ hops: number;
290
+ }
291
+ export declare function nearestNamedOwner(node: IHeapNode, opts?: {
292
+ maxHops?: number;
293
+ }): NamedOwner | null;
294
+ export interface EphemeronEdge {
295
+ keyName: string;
296
+ keyId: number;
297
+ valueName: string;
298
+ valueId: number;
299
+ }
300
+ /** Parse a WeakMap ephemeron edge name, or `null` if it is an ordinary edge. */
301
+ export declare function parseEphemeronEdge(edgeName: string | undefined | null): EphemeronEdge | null;
302
+ /**
303
+ * The caveat to print when a path traverses an ephemeron edge. `atTarget` marks
304
+ * the case where it is the LAST hop, which is the one that invalidates the
305
+ * conclusion outright rather than merely complicating it.
306
+ */
307
+ export declare function ephemeronCaveat(eph: EphemeronEdge, atTarget: boolean): string;
152
308
  export declare function formatBytes(bytes: number): string;
153
309
  export declare function formatNumber(n: number): string;
154
310
  export declare function markdownTable(headers: string[], rows: string[][], alignRight?: Set<number>): string;
@@ -169,7 +325,39 @@ export interface RetainerTreeStep {
169
325
  edgeName?: string;
170
326
  collapsedBefore?: number;
171
327
  collapsedNote?: string;
328
+ repeatCount?: number;
172
329
  }
330
+ /**
331
+ * Collapse runs of consecutive same-class hops in a retainer path into a single
332
+ * step tagged with `repeatCount`.
333
+ *
334
+ * Linked structures (a React hook update queue's `pending → .next → .next → …`,
335
+ * intrusive lists, promise chains) produce paths that are hundreds of identical
336
+ * `Object → Object → Object` hops long. Rendering every hop costs thousands of
337
+ * tokens and tells the reader nothing the count doesn't: the interesting part is
338
+ * the chain's head, its length, and where it attaches. This keeps the first hop
339
+ * of each run (so the edge into the run is preserved) and folds the rest.
340
+ *
341
+ * Only runs of at least `minRun` are collapsed, so ordinary short paths render
342
+ * exactly as before.
343
+ */
344
+ export declare function collapseRepeatedRuns(steps: RetainerTreeStep[], minRun?: number): RetainerTreeStep[];
345
+ /**
346
+ * Collapse runs of an identical rendered label, for formatters that have already
347
+ * reduced each hop to a string. Mirrors `collapseRepeatedRuns` for chain-style
348
+ * (`A → B → C`) renderers.
349
+ */
350
+ export declare function collapseRepeatedLabels(labels: string[], minRun?: number): string[];
351
+ /**
352
+ * One-line note describing what a tool's thresholds excluded from its own
353
+ * output. Printing this everywhere a default threshold exists prevents the
354
+ * failure mode where a tool reports "0" or "none found" and the reader takes it
355
+ * as "there is nothing there", when in fact everything interesting was below the
356
+ * cutoff. (A `dev_artifacts` run reporting `0 B` dev-only — because every
357
+ * console-retained string was under the 512 KB default — nearly landed a
358
+ * measurement artifact in a diff as a production leak.)
359
+ */
360
+ export declare function describeSkipped(examined: number, skipped: number, thresholdLabel: string): string;
173
361
  /**
174
362
  * Render a retainer path so it reads in a single, unambiguous direction: the GC
175
363
  * root is at the top, and **every node is retained by the one above it**. The
@@ -191,15 +379,57 @@ export declare function formatRetainerTree(steps: RetainerTreeStep[], opts?: {
191
379
  maxTreeDepth?: number;
192
380
  }): string;
193
381
  export declare function formatNodeSummaryTable(nodes: NodeSummary[]): string;
382
+ /**
383
+ * Legend for elided C++ template arguments, emitted only when something in the
384
+ * rendered output actually carries the marker — an unconditional legend is the
385
+ * same token tax the abbreviation exists to remove.
386
+ */
387
+ export declare function blinkLegend(rendered: Iterable<string>): string;
194
388
  export declare function formatQueryNodesResult(result: QueryNodesResult, offset?: number): string;
389
+ /**
390
+ * Build a name filter from a caller-supplied pattern.
391
+ *
392
+ * Interpreted as a case-insensitive regular expression, falling back to a plain
393
+ * case-insensitive substring test when the pattern is not valid regex — so a
394
+ * literal like `blink::UndoStep` works without escaping and a real pattern
395
+ * still works. An empty/absent pattern matches everything.
396
+ *
397
+ * Why this exists: answering "is `blink::UndoStep` present?" previously meant
398
+ * `class_histogram({node_type: "native", limit: 200})` and reading ~4 KB of
399
+ * table for one row. Filtering at the source is the difference between a
400
+ * yes/no answer and a page of output.
401
+ */
402
+ export declare function makeNamePatternTest(pattern: string | undefined): (name: string) => boolean;
195
403
  export declare function snapshotHeader(): string;
404
+ /**
405
+ * The header for a tool that read snapshots given as PATHS.
406
+ *
407
+ * `snapshotHeader()` can only ever describe the RESIDENT snapshot, because that
408
+ * is the only one the session knows about. For a path-taking tool that is the
409
+ * wrong file by construction whenever the caller has something else loaded —
410
+ * and these tools restore the caller's active snapshot before they build their
411
+ * result (see `withSnapshotAt`), so by the time the header is rendered the
412
+ * snapshot it names is never the one that was measured.
413
+ *
414
+ * Measured across a 12-round investigation: every path-based call printed a
415
+ * header naming a capture from an earlier round. A ladder result labelled with
416
+ * another round's rung is a cross-round misattribution hazard in exactly the
417
+ * workflow these tools exist for, so name what was actually read.
418
+ */
419
+ export declare function pathsHeader(labels: readonly string[]): string;
196
420
  export declare function textResult(text: string): {
197
421
  content: {
198
422
  type: "text";
199
423
  text: string;
200
424
  }[];
201
425
  };
202
- export declare function toolResult(text: string): {
426
+ /**
427
+ * @param headerOverride Pass `pathsHeader([...])` when the tool read snapshots
428
+ * by PATH rather than operating on the resident one. Passing `null` suppresses
429
+ * the header entirely. Omitting it keeps the session-header behaviour, which is
430
+ * correct only for tools that genuinely act on the active snapshot.
431
+ */
432
+ export declare function toolResult(text: string, headerOverride?: string | null): {
203
433
  content: {
204
434
  type: "text";
205
435
  text: string;
@@ -208,9 +438,14 @@ export declare function toolResult(text: string): {
208
438
  /**
209
439
  * Whether tools should omit "Suggested next steps" / "How to fix" trailers.
210
440
  * Honors the session-level `suppressSuggestions` config so callers can trim
211
- * repeated boilerplate tokens across a long investigation.
441
+ * repeated boilerplate tokens across a long investigation, and self-suppresses
442
+ * after `SUGGESTION_TRAILER_BUDGET` trailers.
443
+ *
444
+ * NOTE: this both reads and ADVANCES the budget, so call it once per decision.
212
445
  */
213
446
  export declare function suggestionsSuppressed(): boolean;
447
+ /** Test seam; also reset when the session config is changed explicitly. */
448
+ export declare function resetSuggestionBudget(): void;
214
449
  export declare function jsonResult(data: unknown): {
215
450
  content: {
216
451
  type: "text";
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}