@memlab/mcp-server 2.52.0 → 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 (277) hide show
  1. package/README.md +22 -2
  2. package/dist/anonymized-snapshot.d.ts +75 -0
  3. package/dist/anonymized-snapshot.d.ts.map +1 -0
  4. package/dist/anonymized-snapshot.js +101 -0
  5. package/dist/anonymized-snapshot.js.map +1 -0
  6. package/dist/eval-hints.d.ts +41 -0
  7. package/dist/eval-hints.d.ts.map +1 -0
  8. package/dist/eval-hints.js +115 -0
  9. package/dist/eval-hints.js.map +1 -0
  10. package/dist/heap-budget.d.ts +32 -0
  11. package/dist/heap-budget.d.ts.map +1 -0
  12. package/dist/heap-budget.js +90 -0
  13. package/dist/heap-budget.js.map +1 -0
  14. package/dist/heap-shapes.d.ts +148 -0
  15. package/dist/heap-shapes.d.ts.map +1 -0
  16. package/dist/heap-shapes.js +193 -0
  17. package/dist/heap-shapes.js.map +1 -0
  18. package/dist/heap-state.d.ts +20 -0
  19. package/dist/heap-state.d.ts.map +1 -1
  20. package/dist/heap-state.js +8 -1
  21. package/dist/heap-state.js.map +1 -1
  22. package/dist/index.js +64 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/react-shapes.d.ts +42 -0
  25. package/dist/react-shapes.d.ts.map +1 -0
  26. package/dist/react-shapes.js +149 -0
  27. package/dist/react-shapes.js.map +1 -0
  28. package/dist/server-version.d.ts +19 -0
  29. package/dist/server-version.d.ts.map +1 -0
  30. package/dist/server-version.js +19 -0
  31. package/dist/server-version.js.map +1 -0
  32. package/dist/snapshot-borrow.d.ts +67 -0
  33. package/dist/snapshot-borrow.d.ts.map +1 -0
  34. package/dist/snapshot-borrow.js +113 -0
  35. package/dist/snapshot-borrow.js.map +1 -0
  36. package/dist/string-index.d.ts.map +1 -1
  37. package/dist/string-index.js +8 -0
  38. package/dist/string-index.js.map +1 -1
  39. package/dist/tools/analyze-run.d.ts.map +1 -1
  40. package/dist/tools/analyze-run.js +79 -18
  41. package/dist/tools/analyze-run.js.map +1 -1
  42. package/dist/tools/anonymize-snapshot.d.ts +12 -0
  43. package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
  44. package/dist/tools/anonymize-snapshot.js +159 -0
  45. package/dist/tools/anonymize-snapshot.js.map +1 -0
  46. package/dist/tools/app-config.d.ts +12 -0
  47. package/dist/tools/app-config.d.ts.map +1 -0
  48. package/dist/tools/app-config.js +217 -0
  49. package/dist/tools/app-config.js.map +1 -0
  50. package/dist/tools/app-heap.d.ts +18 -0
  51. package/dist/tools/app-heap.d.ts.map +1 -1
  52. package/dist/tools/app-heap.js +12 -46
  53. package/dist/tools/app-heap.js.map +1 -1
  54. package/dist/tools/artifact-budget.d.ts +12 -0
  55. package/dist/tools/artifact-budget.d.ts.map +1 -0
  56. package/dist/tools/artifact-budget.js +219 -0
  57. package/dist/tools/artifact-budget.js.map +1 -0
  58. package/dist/tools/async-census.d.ts +12 -0
  59. package/dist/tools/async-census.d.ts.map +1 -0
  60. package/dist/tools/async-census.js +243 -0
  61. package/dist/tools/async-census.js.map +1 -0
  62. package/dist/tools/auto-investigate.d.ts.map +1 -1
  63. package/dist/tools/auto-investigate.js +54 -5
  64. package/dist/tools/auto-investigate.js.map +1 -1
  65. package/dist/tools/batch.d.ts.map +1 -1
  66. package/dist/tools/batch.js +33 -5
  67. package/dist/tools/batch.js.map +1 -1
  68. package/dist/tools/cache-analysis.d.ts +15 -0
  69. package/dist/tools/cache-analysis.d.ts.map +1 -1
  70. package/dist/tools/cache-analysis.js +85 -10
  71. package/dist/tools/cache-analysis.js.map +1 -1
  72. package/dist/tools/census-diff.d.ts +55 -0
  73. package/dist/tools/census-diff.d.ts.map +1 -0
  74. package/dist/tools/census-diff.js +228 -0
  75. package/dist/tools/census-diff.js.map +1 -0
  76. package/dist/tools/chain-walk.d.ts +12 -0
  77. package/dist/tools/chain-walk.d.ts.map +1 -0
  78. package/dist/tools/chain-walk.js +184 -0
  79. package/dist/tools/chain-walk.js.map +1 -0
  80. package/dist/tools/collection-diff.d.ts +44 -0
  81. package/dist/tools/collection-diff.d.ts.map +1 -0
  82. package/dist/tools/collection-diff.js +343 -0
  83. package/dist/tools/collection-diff.js.map +1 -0
  84. package/dist/tools/collection-trend.d.ts.map +1 -1
  85. package/dist/tools/collection-trend.js +2 -2
  86. package/dist/tools/collection-trend.js.map +1 -1
  87. package/dist/tools/detached-dom.d.ts +3 -0
  88. package/dist/tools/detached-dom.d.ts.map +1 -1
  89. package/dist/tools/detached-dom.js +78 -3
  90. package/dist/tools/detached-dom.js.map +1 -1
  91. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  92. package/dist/tools/dev-artifacts.js +221 -3
  93. package/dist/tools/dev-artifacts.js.map +1 -1
  94. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  95. package/dist/tools/diff-snapshots.js +18 -2
  96. package/dist/tools/diff-snapshots.js.map +1 -1
  97. package/dist/tools/dom-audit.d.ts +37 -0
  98. package/dist/tools/dom-audit.d.ts.map +1 -0
  99. package/dist/tools/dom-audit.js +247 -0
  100. package/dist/tools/dom-audit.js.map +1 -0
  101. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  102. package/dist/tools/duplicated-strings.js +3 -2
  103. package/dist/tools/duplicated-strings.js.map +1 -1
  104. package/dist/tools/eval-across.d.ts +12 -0
  105. package/dist/tools/eval-across.d.ts.map +1 -0
  106. package/dist/tools/eval-across.js +135 -0
  107. package/dist/tools/eval-across.js.map +1 -0
  108. package/dist/tools/eval.d.ts +78 -0
  109. package/dist/tools/eval.d.ts.map +1 -1
  110. package/dist/tools/eval.js +2270 -701
  111. package/dist/tools/eval.js.map +1 -1
  112. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  113. package/dist/tools/event-listener-leaks.js +42 -17
  114. package/dist/tools/event-listener-leaks.js.map +1 -1
  115. package/dist/tools/event-registry.d.ts.map +1 -1
  116. package/dist/tools/event-registry.js +42 -8
  117. package/dist/tools/event-registry.js.map +1 -1
  118. package/dist/tools/explain-delta.d.ts.map +1 -1
  119. package/dist/tools/explain-delta.js +61 -10
  120. package/dist/tools/explain-delta.js.map +1 -1
  121. package/dist/tools/finding-index.d.ts +181 -0
  122. package/dist/tools/finding-index.d.ts.map +1 -1
  123. package/dist/tools/finding-index.js +343 -24
  124. package/dist/tools/finding-index.js.map +1 -1
  125. package/dist/tools/get-value.d.ts +16 -0
  126. package/dist/tools/get-value.d.ts.map +1 -1
  127. package/dist/tools/get-value.js +96 -2
  128. package/dist/tools/get-value.js.map +1 -1
  129. package/dist/tools/hypothesis.d.ts.map +1 -1
  130. package/dist/tools/hypothesis.js +117 -58
  131. package/dist/tools/hypothesis.js.map +1 -1
  132. package/dist/tools/id-space-audit.d.ts +12 -0
  133. package/dist/tools/id-space-audit.d.ts.map +1 -0
  134. package/dist/tools/id-space-audit.js +262 -0
  135. package/dist/tools/id-space-audit.js.map +1 -0
  136. package/dist/tools/identify.d.ts +12 -0
  137. package/dist/tools/identify.d.ts.map +1 -0
  138. package/dist/tools/identify.js +205 -0
  139. package/dist/tools/identify.js.map +1 -0
  140. package/dist/tools/identity-diff.d.ts +12 -0
  141. package/dist/tools/identity-diff.d.ts.map +1 -0
  142. package/dist/tools/identity-diff.js +188 -0
  143. package/dist/tools/identity-diff.js.map +1 -0
  144. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  145. package/dist/tools/intern-opportunities.js +4 -3
  146. package/dist/tools/intern-opportunities.js.map +1 -1
  147. package/dist/tools/ladder-probe.d.ts +65 -0
  148. package/dist/tools/ladder-probe.d.ts.map +1 -0
  149. package/dist/tools/ladder-probe.js +445 -0
  150. package/dist/tools/ladder-probe.js.map +1 -0
  151. package/dist/tools/ladder.d.ts.map +1 -1
  152. package/dist/tools/ladder.js +5 -5
  153. package/dist/tools/ladder.js.map +1 -1
  154. package/dist/tools/leak-report.d.ts +23 -0
  155. package/dist/tools/leak-report.d.ts.map +1 -1
  156. package/dist/tools/leak-report.js +153 -11
  157. package/dist/tools/leak-report.js.map +1 -1
  158. package/dist/tools/load-snapshot.d.ts +11 -0
  159. package/dist/tools/load-snapshot.d.ts.map +1 -1
  160. package/dist/tools/load-snapshot.js +83 -10
  161. package/dist/tools/load-snapshot.js.map +1 -1
  162. package/dist/tools/metric.d.ts +13 -0
  163. package/dist/tools/metric.d.ts.map +1 -0
  164. package/dist/tools/metric.js +185 -0
  165. package/dist/tools/metric.js.map +1 -0
  166. package/dist/tools/module-attribution.d.ts +36 -0
  167. package/dist/tools/module-attribution.d.ts.map +1 -0
  168. package/dist/tools/module-attribution.js +235 -0
  169. package/dist/tools/module-attribution.js.map +1 -0
  170. package/dist/tools/next-measurement.d.ts +26 -0
  171. package/dist/tools/next-measurement.d.ts.map +1 -0
  172. package/dist/tools/next-measurement.js +149 -0
  173. package/dist/tools/next-measurement.js.map +1 -0
  174. package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
  175. package/dist/tools/object-cost-breakdown.js +64 -0
  176. package/dist/tools/object-cost-breakdown.js.map +1 -1
  177. package/dist/tools/population-vs-owners.d.ts +12 -0
  178. package/dist/tools/population-vs-owners.d.ts.map +1 -0
  179. package/dist/tools/population-vs-owners.js +183 -0
  180. package/dist/tools/population-vs-owners.js.map +1 -0
  181. package/dist/tools/property-names.d.ts +29 -0
  182. package/dist/tools/property-names.d.ts.map +1 -0
  183. package/dist/tools/property-names.js +131 -0
  184. package/dist/tools/property-names.js.map +1 -0
  185. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  186. package/dist/tools/quick-diagnosis.js +7 -1
  187. package/dist/tools/quick-diagnosis.js.map +1 -1
  188. package/dist/tools/react-owners.d.ts +12 -0
  189. package/dist/tools/react-owners.d.ts.map +1 -0
  190. package/dist/tools/react-owners.js +167 -0
  191. package/dist/tools/react-owners.js.map +1 -0
  192. package/dist/tools/react-update-queues.d.ts +12 -0
  193. package/dist/tools/react-update-queues.d.ts.map +1 -0
  194. package/dist/tools/react-update-queues.js +173 -0
  195. package/dist/tools/react-update-queues.js.map +1 -0
  196. package/dist/tools/replicate.d.ts +49 -0
  197. package/dist/tools/replicate.d.ts.map +1 -0
  198. package/dist/tools/replicate.js +241 -0
  199. package/dist/tools/replicate.js.map +1 -0
  200. package/dist/tools/retainer-diff.d.ts +12 -0
  201. package/dist/tools/retainer-diff.d.ts.map +1 -0
  202. package/dist/tools/retainer-diff.js +168 -0
  203. package/dist/tools/retainer-diff.js.map +1 -0
  204. package/dist/tools/retainer-summary.d.ts +17 -0
  205. package/dist/tools/retainer-summary.d.ts.map +1 -1
  206. package/dist/tools/retainer-summary.js +85 -22
  207. package/dist/tools/retainer-summary.js.map +1 -1
  208. package/dist/tools/retainer-trace.d.ts.map +1 -1
  209. package/dist/tools/retainer-trace.js +11 -1
  210. package/dist/tools/retainer-trace.js.map +1 -1
  211. package/dist/tools/round-audit.d.ts +66 -0
  212. package/dist/tools/round-audit.d.ts.map +1 -0
  213. package/dist/tools/round-audit.js +258 -0
  214. package/dist/tools/round-audit.js.map +1 -0
  215. package/dist/tools/round-digest.d.ts +12 -0
  216. package/dist/tools/round-digest.d.ts.map +1 -0
  217. package/dist/tools/round-digest.js +190 -0
  218. package/dist/tools/round-digest.js.map +1 -0
  219. package/dist/tools/script-census.d.ts +12 -0
  220. package/dist/tools/script-census.d.ts.map +1 -0
  221. package/dist/tools/script-census.js +182 -0
  222. package/dist/tools/script-census.js.map +1 -0
  223. package/dist/tools/sequence-analysis.d.ts +4 -0
  224. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  225. package/dist/tools/sequence-analysis.js +53 -9
  226. package/dist/tools/sequence-analysis.js.map +1 -1
  227. package/dist/tools/server-status.d.ts.map +1 -1
  228. package/dist/tools/server-status.js +4 -1
  229. package/dist/tools/server-status.js.map +1 -1
  230. package/dist/tools/settle-check.d.ts +12 -0
  231. package/dist/tools/settle-check.d.ts.map +1 -0
  232. package/dist/tools/settle-check.js +188 -0
  233. package/dist/tools/settle-check.js.map +1 -0
  234. package/dist/tools/sliced-strings.d.ts.map +1 -1
  235. package/dist/tools/sliced-strings.js +2 -1
  236. package/dist/tools/sliced-strings.js.map +1 -1
  237. package/dist/tools/snapshots.d.ts.map +1 -1
  238. package/dist/tools/snapshots.js +24 -6
  239. package/dist/tools/snapshots.js.map +1 -1
  240. package/dist/tools/sparse-elements.d.ts +12 -0
  241. package/dist/tools/sparse-elements.d.ts.map +1 -0
  242. package/dist/tools/sparse-elements.js +215 -0
  243. package/dist/tools/sparse-elements.js.map +1 -0
  244. package/dist/tools/stale-collections.d.ts +17 -0
  245. package/dist/tools/stale-collections.d.ts.map +1 -1
  246. package/dist/tools/stale-collections.js +28 -0
  247. package/dist/tools/stale-collections.js.map +1 -1
  248. package/dist/tools/string-patterns.d.ts.map +1 -1
  249. package/dist/tools/string-patterns.js +2 -1
  250. package/dist/tools/string-patterns.js.map +1 -1
  251. package/dist/tools/tools-index.d.ts.map +1 -1
  252. package/dist/tools/tools-index.js +155 -5
  253. package/dist/tools/tools-index.js.map +1 -1
  254. package/dist/tools/trace-all.d.ts +42 -0
  255. package/dist/tools/trace-all.d.ts.map +1 -0
  256. package/dist/tools/trace-all.js +263 -0
  257. package/dist/tools/trace-all.js.map +1 -0
  258. package/dist/tools/unit-cost.d.ts +12 -0
  259. package/dist/tools/unit-cost.d.ts.map +1 -0
  260. package/dist/tools/unit-cost.js +219 -0
  261. package/dist/tools/unit-cost.js.map +1 -0
  262. package/dist/tools/verify-fix.d.ts.map +1 -1
  263. package/dist/tools/verify-fix.js +11 -3
  264. package/dist/tools/verify-fix.js.map +1 -1
  265. package/dist/tools/weakref-census.d.ts +15 -0
  266. package/dist/tools/weakref-census.d.ts.map +1 -0
  267. package/dist/tools/weakref-census.js +147 -0
  268. package/dist/tools/weakref-census.js.map +1 -0
  269. package/dist/tools/what-if.d.ts +12 -0
  270. package/dist/tools/what-if.d.ts.map +1 -0
  271. package/dist/tools/what-if.js +285 -0
  272. package/dist/tools/what-if.js.map +1 -0
  273. package/dist/utils.d.ts +92 -2
  274. package/dist/utils.d.ts.map +1 -1
  275. package/dist/utils.js +172 -5
  276. package/dist/utils.js.map +1 -1
  277. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-space-audit.js","sourceRoot":"","sources":["../../src/tools/id-space-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
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 type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ export declare function registerIdentify(server: McpServer): void;
12
+ //# sourceMappingURL=identify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identify.d.ts","sourceRoot":"","sources":["../../src/tools/identify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAmIvE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8IxD"}
@@ -0,0 +1,205 @@
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 { z } from 'zod';
11
+ import { getSnapshot } from '../heap-state.js';
12
+ import { errorResult, formatNumber, markdownTable, toolResult, } from '../utils.js';
13
+ const FINGERPRINTS = [
14
+ {
15
+ name: 'React update-queue record',
16
+ required: ['action', 'next'],
17
+ optional: ['eagerState', 'hasEagerState', 'lane'],
18
+ what: 'One queued useState/useReducer update on a hook, in a circular linked list at `queue.pending`.',
19
+ matters: "A record carrying `hasEagerState: true` whose `eagerState` is the queue's current state is a NO-OP update: React took the eager-state bailout, scheduled no render, and nothing ever drains the queue. On a component that never unmounts these accumulate for the lifetime of the tab.",
20
+ },
21
+ {
22
+ name: 'React scheduler task',
23
+ required: ['callback', 'priorityLevel', 'sortIndex'],
24
+ optional: ['expirationTime', 'startTime', 'id'],
25
+ what: "An entry in the `scheduler` package's min-heap task queue.",
26
+ matters: 'A `callback` of null means the task was cancelled or has already run; the scheduler only drops it when it surfaces at the top of the heap. A deep queue mid-burst is normal — check it again after the app settles before calling it a leak.',
27
+ },
28
+ {
29
+ name: 'React hook state',
30
+ required: ['memoizedState', 'next', 'queue'],
31
+ optional: ['baseQueue', 'baseState'],
32
+ what: "One hook in a fiber's hook list.",
33
+ matters: 'Counts scale with mounted components. Growth without a matching rise in rendered UI means fibers are being retained after unmount.',
34
+ },
35
+ {
36
+ name: 'Observer/emitter listener record',
37
+ required: ['callback', 'context'],
38
+ absent: ['priorityLevel'],
39
+ what: "A Backbone-style `{callback, context}` pair in an emitter's per-event listener array.",
40
+ matters: 'Two different leaks share this shape: the same (callback, context) registered repeatedly, and many DISTINCT contexts piling up on one long-lived emitter (a `listenTo` with no `stopListening`). The second produces no duplicates at all — check the per-host distribution, not just duplicate pairs.',
41
+ },
42
+ {
43
+ name: 'LRU list node',
44
+ required: ['key', 'next', 'prev', 'value'],
45
+ what: 'A doubly-linked-list node in an LRU cache (the recency list beside the Map).',
46
+ matters: "The node count is the cache's live entry count, so it is the cheapest way to see whether a configured cap is actually binding. `memlab_unit_cost` on this shape gives the per-entry cost a cap is sized against.",
47
+ },
48
+ {
49
+ name: 'Promise-library deferred (Dexie/Bluebird style)',
50
+ required: ['_listeners'],
51
+ optional: ['_PSD', '_state', '_value', 'onuncatched'],
52
+ what: 'A userland promise object with its own listener list and zone/context handle.',
53
+ matters: 'When the zone handle (`_PSD`) carries a transaction, the promise pins that transaction and everything it holds. Large populations are usually in-flight work — confirm with a post-idle capture (`memlab_settle_check`) before treating them as retention.',
54
+ },
55
+ {
56
+ name: 'Editor history entry (Lexical/ProseMirror style)',
57
+ required: ['editorState'],
58
+ optional: ['undoStack', 'redoStack', 'current'],
59
+ what: 'One immutable editor state snapshot on an undo stack.',
60
+ matters: 'Undo stacks are usually unbounded unless the host passes a depth limit, and each entry clones the whole document node map. Growth is per keystroke-group, released only when the editor unmounts.',
61
+ },
62
+ {
63
+ name: 'Timer/interval registry entry',
64
+ required: ['callback'],
65
+ optional: ['delay', 'timerId', 'repeat'],
66
+ absent: ['context', 'priorityLevel'],
67
+ what: 'A pending timer record held by a timer wrapper or scheduler shim.',
68
+ matters: "Entries that outlive their `clearTimeout`/`clearInterval` keep their callback's entire closure scope alive.",
69
+ },
70
+ ];
71
+ function propsOf(node, cap = 200) {
72
+ const out = new Set();
73
+ let seen = 0;
74
+ for (const edge of node.references) {
75
+ if (edge.type !== 'property')
76
+ continue;
77
+ out.add(String(edge.name_or_index));
78
+ if (++seen >= cap)
79
+ break;
80
+ }
81
+ return out;
82
+ }
83
+ function matchFingerprints(props) {
84
+ const matches = [];
85
+ for (const fp of FINGERPRINTS) {
86
+ if (!fp.required.every(p => props.has(p)))
87
+ continue;
88
+ if (fp.absent?.some(p => props.has(p)))
89
+ continue;
90
+ const matchedOptional = (fp.optional ?? []).filter(p => props.has(p));
91
+ // Required properties carry the match; optional ones only rank it.
92
+ const score = fp.required.length * 2 +
93
+ matchedOptional.length +
94
+ (fp.absent != null ? 0.5 : 0);
95
+ matches.push({ fp, score, matchedOptional });
96
+ }
97
+ return matches.sort((a, b) => b.score - a.score);
98
+ }
99
+ export function registerIdentify(server) {
100
+ server.tool('memlab_identify', 'Name a minified structure from its property shape. In a production bundle nearly every class is `t`, `e`, `s` or `Object`, so the first — and often longest — step of an investigation is working out what a population actually IS: a listener record, an LRU node, a React update record, an editor-history entry. This matches a node (or a bare shape) against a library of known fingerprints and reports what it is, why it matters, and what to check next.\n\n' +
101
+ 'Give it a `node_id`, or a `shape` you already have from `memlab_shape_histogram` / `memlab_find_by_shape`. With `scan: true` it sweeps the whole heap and reports every recognised structure with its population count, which is a fast way to orient in an unfamiliar app.\n\n' +
102
+ 'A name here is a strong hypothesis, not proof: shapes collide across libraries, so confirm with a retainer trace before writing it into a report.', {
103
+ node_id: z
104
+ .number()
105
+ .optional()
106
+ .describe('Identify this node from its properties.'),
107
+ shape: z
108
+ .array(z.string())
109
+ .optional()
110
+ .describe('Identify a property set directly, e.g. ["callback","context"] — useful with output from memlab_shape_histogram.'),
111
+ scan: z
112
+ .boolean()
113
+ .optional()
114
+ .default(false)
115
+ .describe('Sweep the whole heap and report every recognised structure with its instance count (default false).'),
116
+ limit: z
117
+ .number()
118
+ .optional()
119
+ .default(15)
120
+ .describe('Maximum rows in scan mode (default 15).'),
121
+ }, async ({ node_id, shape, scan, limit }) => {
122
+ try {
123
+ const snapshot = getSnapshot({ allowLight: true });
124
+ if (scan) {
125
+ const counts = new Map();
126
+ snapshot.nodes.forEach(node => {
127
+ if (node.id <= 3 || node.type !== 'object')
128
+ return;
129
+ const props = propsOf(node, 40);
130
+ if (props.size === 0)
131
+ return;
132
+ const best = matchFingerprints(props)[0];
133
+ if (best == null)
134
+ return;
135
+ counts.set(best.fp.name, (counts.get(best.fp.name) ?? 0) + 1);
136
+ });
137
+ if (counts.size === 0) {
138
+ return toolResult('No known structures recognised in this heap. The fingerprint library covers React internals, observer/emitter listener records, LRU nodes, userland promise deferreds, editor history and timer registries — an app built on other libraries will match none of them, which is a gap in the library rather than a fact about the heap.');
139
+ }
140
+ const rows = [...counts.entries()]
141
+ .sort((a, b) => b[1] - a[1])
142
+ .slice(0, limit)
143
+ .map(([name, count]) => {
144
+ const fp = FINGERPRINTS.find(f => f.name === name);
145
+ return [
146
+ name,
147
+ formatNumber(count),
148
+ `{${(fp?.required ?? []).join(', ')}}`,
149
+ ];
150
+ });
151
+ return toolResult([
152
+ '## Recognised structures',
153
+ '',
154
+ markdownTable(['Structure', 'Instances', 'Required shape'], rows, new Set([1])),
155
+ '',
156
+ '_Matched on property shape alone. Shapes collide across libraries — confirm a population with `memlab_retainer_trace` before acting on the name. Counts here are of objects whose BEST match is that fingerprint._',
157
+ '',
158
+ 'Next: `memlab_unit_cost` for what one of them costs, `memlab_identify({node_id})` for why a specific one matters.',
159
+ ].join('\n'));
160
+ }
161
+ let props;
162
+ let subject;
163
+ if (node_id != null) {
164
+ const node = snapshot.getNodeById(node_id);
165
+ if (node == null) {
166
+ return errorResult(new Error(`Node ${node_id} not found. Node ids are per-capture — check you are on the snapshot the id came from (memlab_snapshots).`));
167
+ }
168
+ props = propsOf(node);
169
+ subject = `@${node_id} \`${node.name}\` (${node.type})`;
170
+ }
171
+ else if (shape != null && shape.length > 0) {
172
+ props = new Set(shape);
173
+ subject = `shape \`{${shape.join(', ')}}\``;
174
+ }
175
+ else {
176
+ return errorResult(new Error('Pass node_id or shape (or scan: true).'));
177
+ }
178
+ const matches = matchFingerprints(props);
179
+ if (matches.length === 0) {
180
+ return toolResult([
181
+ `## ${subject}`,
182
+ '',
183
+ `Properties: \`{${[...props].slice(0, 25).join(', ')}}\`${props.size > 25 ? ` … +${props.size - 25}` : ''}`,
184
+ '',
185
+ '**No fingerprint matched.** That is a statement about the library here, not about the object: it covers React internals, observer/emitter listener records, LRU nodes, userland promise deferreds, editor history and timer registries.',
186
+ '',
187
+ 'To identify it by hand: `memlab_referrer_summary` (who holds it, which usually names it), `memlab_object_shape` on a few instances (which properties are stable), and `memlab_retainer_trace` (which subsystem it hangs off).',
188
+ ].join('\n'));
189
+ }
190
+ const lines = [`## ${subject}`, ''];
191
+ matches.slice(0, 3).forEach((m, i) => {
192
+ lines.push(`### ${i === 0 ? '' : 'Also matches: '}${m.fp.name}${i === 0 && matches.length > 1 ? ' (best match)' : ''}`, '', `**What it is:** ${m.fp.what}`, '', `**Why it matters:** ${m.fp.matters}`, '', `Matched on \`{${m.fp.required.join(', ')}}\`${m.matchedOptional.length > 0 ? ` plus \`${m.matchedOptional.join('`, `')}\`` : ''}.`, '');
193
+ });
194
+ if (matches.length > 1) {
195
+ lines.push(`_${matches.length} fingerprints matched; shapes collide, so treat the ranking as a hypothesis and confirm with a retainer trace._`, '');
196
+ }
197
+ lines.push('Next: `memlab_unit_cost` for the per-instance cost, `memlab_retainer_trace` to confirm the owner.');
198
+ return toolResult(lines.join('\n'));
199
+ }
200
+ catch (err) {
201
+ return errorResult(err);
202
+ }
203
+ });
204
+ }
205
+ //# sourceMappingURL=identify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identify.js","sourceRoot":"","sources":["../../src/tools/identify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
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 type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ export declare function registerIdentityDiff(server: McpServer): void;
12
+ //# sourceMappingURL=identity-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-diff.d.ts","sourceRoot":"","sources":["../../src/tools/identity-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAkEvE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyL5D"}
@@ -0,0 +1,188 @@
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 { z } from 'zod';
11
+ import { getCurrentHandle, getMetadataByHandle, getSnapshotByHandle, listSnapshots, } from '../heap-state.js';
12
+ import { selectPopulation } from './trace-all.js';
13
+ import { errorResult, formatNumber, markdownTable, toolResult, } from '../utils.js';
14
+ /**
15
+ * Node ids are per-capture, so nothing in a snapshot pair says whether two
16
+ * populations of the same size are the SAME objects. That distinction decides
17
+ * what kind of bug is in front of you: a population that is churning (old
18
+ * members replaced by new ones) is a rate problem, while one whose members all
19
+ * persist is retention, and the two have different fixes. Counting cannot tell
20
+ * them apart, and a count is what every existing diff reports.
21
+ *
22
+ * A content key stands in for identity: the object's property names plus the
23
+ * string values it holds. It is not a true identity — two objects with the same
24
+ * content are indistinguishable to it, which is exactly why the number of
25
+ * distinct keys is reported alongside the population size. When keys collide
26
+ * heavily the answer is weak, and the tool says so rather than implying that
27
+ * "80% persisted" is a fact about object identity.
28
+ */
29
+ function contentKey(node, maxValues) {
30
+ const props = [];
31
+ const values = [];
32
+ for (const edge of node.references) {
33
+ if (edge.type !== 'property')
34
+ continue;
35
+ const name = String(edge.name_or_index);
36
+ props.push(name);
37
+ if (values.length < maxValues) {
38
+ const target = edge.toNode;
39
+ if (target.type === 'string' || target.type === 'concatenated string') {
40
+ values.push(`${name}=${target.name.slice(0, 64)}`);
41
+ }
42
+ else if (target.name === 'true' || target.name === 'false') {
43
+ values.push(`${name}=${target.name}`);
44
+ }
45
+ }
46
+ }
47
+ props.sort();
48
+ values.sort();
49
+ return `{${props.join(',')}}|${values.join('|')}`;
50
+ }
51
+ function keyCounts(snapshot, sel, maxValues) {
52
+ const counts = new Map();
53
+ const nodes = selectPopulation(snapshot, sel);
54
+ for (const node of nodes) {
55
+ const k = contentKey(node, maxValues);
56
+ counts.set(k, (counts.get(k) ?? 0) + 1);
57
+ }
58
+ return { counts, total: nodes.length };
59
+ }
60
+ export function registerIdentityDiff(server) {
61
+ server.tool('memlab_identity_diff', 'Same objects, or just the same number of objects? Matches a population across two snapshots by CONTENT rather than by node id, which is not comparable across captures.\n\n' +
62
+ 'The distinction decides what kind of bug this is. A population whose members are replaced between captures is churn — a rate problem, and capping or reusing is the fix. A population whose members all persist is retention, and the fix is releasing them. The two look identical in every count-based diff, which is what `memlab_diff_snapshots` and a class histogram report.\n\n' +
63
+ "The content key is the object's property names plus the string and boolean values it holds. That is a stand-in for identity, not identity: objects with identical content are indistinguishable to it. The report always states how distinct the keys actually were, so a weak answer is visible as one.", {
64
+ before_handle: z
65
+ .string()
66
+ .describe('Handle of the earlier snapshot (memlab_snapshots lists them).'),
67
+ after_handle: z.string().describe('Handle of the later snapshot.'),
68
+ class_name: z
69
+ .string()
70
+ .optional()
71
+ .describe('Population: every instance of this class.'),
72
+ shape: z
73
+ .array(z.string())
74
+ .optional()
75
+ .describe('Population: every object carrying ALL of these properties — the selector to use on a minified heap.'),
76
+ max_values: z
77
+ .number()
78
+ .optional()
79
+ .default(8)
80
+ .describe('String/boolean property values folded into the key (default 8). More values means a sharper key and more sensitivity to incidental differences; fewer means more collisions.'),
81
+ limit: z
82
+ .number()
83
+ .optional()
84
+ .default(10)
85
+ .describe('Example keys to show per category (default 10).'),
86
+ }, async ({ before_handle, after_handle, class_name, shape, max_values, limit, }) => {
87
+ try {
88
+ if ((class_name == null) === (shape == null || shape.length === 0)) {
89
+ return errorResult(new Error('Pass exactly one of class_name / shape.'));
90
+ }
91
+ if (before_handle === after_handle) {
92
+ return errorResult(new Error('before_handle and after_handle are the same snapshot.'));
93
+ }
94
+ const resolve = (h) => {
95
+ const snap = getSnapshotByHandle(h);
96
+ const meta = getMetadataByHandle(h);
97
+ if (snap == null || meta == null) {
98
+ throw new Error(`No resident snapshot with handle "${h}". Resident: ${listSnapshots()
99
+ .map(m => m.handle)
100
+ .join(', ') || '(none)'}. Load both with memlab_load_snapshot({keep_previous: true}).`);
101
+ }
102
+ return { snap, meta };
103
+ };
104
+ const before = resolve(before_handle);
105
+ const after = resolve(after_handle);
106
+ const sel = { className: class_name, shape };
107
+ const b = keyCounts(before.snap, sel, max_values);
108
+ const a = keyCounts(after.snap, sel, max_values);
109
+ if (b.total === 0 && a.total === 0) {
110
+ return toolResult('The population is empty in both snapshots — nothing to compare.');
111
+ }
112
+ let persisted = 0;
113
+ let gone = 0;
114
+ let appeared = 0;
115
+ const goneKeys = [];
116
+ const newKeys = [];
117
+ for (const [k, n] of b.counts) {
118
+ const after_n = a.counts.get(k) ?? 0;
119
+ persisted += Math.min(n, after_n);
120
+ if (after_n < n) {
121
+ gone += n - after_n;
122
+ goneKeys.push([k, n - after_n]);
123
+ }
124
+ }
125
+ for (const [k, n] of a.counts) {
126
+ const before_n = b.counts.get(k) ?? 0;
127
+ if (n > before_n) {
128
+ appeared += n - before_n;
129
+ newKeys.push([k, n - before_n]);
130
+ }
131
+ }
132
+ goneKeys.sort((x, y) => y[1] - x[1]);
133
+ newKeys.sort((x, y) => y[1] - x[1]);
134
+ const persistShare = b.total > 0 ? (persisted / b.total) * 100 : 0;
135
+ const distinctBefore = b.counts.size;
136
+ const distinctAfter = a.counts.size;
137
+ // A key that covers hundreds of objects cannot distinguish them, so the
138
+ // persisted/churned split it produces is not evidence about identity.
139
+ const collisionsBefore = b.total > 0 ? b.total / Math.max(1, distinctBefore) : 0;
140
+ const collisionsAfter = a.total > 0 ? a.total / Math.max(1, distinctAfter) : 0;
141
+ const weak = Math.max(collisionsBefore, collisionsAfter) >= 10;
142
+ const label = class_name != null
143
+ ? `class \`${class_name}\``
144
+ : `shape \`{${(shape ?? []).join(', ')}}\``;
145
+ const lines = [
146
+ `## Identity of ${label}: ${before.meta.fileName} → ${after.meta.fileName}`,
147
+ '',
148
+ `Population **${formatNumber(b.total)} → ${formatNumber(a.total)}**. Matching by content key: **${formatNumber(persisted)} persisted** (${persistShare.toFixed(1)}% of the earlier population), ${formatNumber(gone)} gone, ${formatNumber(appeared)} new.`,
149
+ '',
150
+ weak
151
+ ? `⚠ **The key is not discriminating here** — ${formatNumber(distinctBefore)} / ${formatNumber(distinctAfter)} distinct keys for ${formatNumber(b.total)} / ${formatNumber(a.total)} objects, so one key covers ~${Math.round(Math.max(collisionsBefore, collisionsAfter))} objects on average. The persisted/churned split above is arithmetic over buckets, NOT evidence about which objects survived. Raise \`max_values\`, or narrow the population first.`
152
+ : `Key resolution: ${formatNumber(distinctBefore)} / ${formatNumber(distinctAfter)} distinct keys for ${formatNumber(b.total)} / ${formatNumber(a.total)} objects — discriminating enough for the split above to mean something.`,
153
+ '',
154
+ weak
155
+ ? '_No verdict: with a key this undiscriminating, "persisted" and "churned" are properties of the buckets, not of the objects. Sharpen the key or narrow the population first._'
156
+ : persistShare >= 90
157
+ ? appeared > 0
158
+ ? '**Retention, not churn:** nearly the whole earlier population is still present AND new members were added. Old members are not being replaced, they are accumulating.'
159
+ : '**Stable population:** the same content is present in both captures and nothing was added. Whatever changed in the heap, it was not this.'
160
+ : persistShare <= 25
161
+ ? '**Churn, not retention:** most of the earlier population is gone and has been replaced. A count that looks flat here is a rate problem, not a leak — capping or reusing is the fix, releasing is not.'
162
+ : 'Mixed: part of the population persists and part turns over. Split it further (by shape or by owner) before treating either reading as the explanation.',
163
+ ];
164
+ if (newKeys.length > 0) {
165
+ lines.push('', '### Content that is new', '', markdownTable(['Count', 'Content key'], newKeys
166
+ .slice(0, limit)
167
+ .map(([k, n]) => [
168
+ formatNumber(n),
169
+ k.length > 100 ? k.slice(0, 97) + '…' : k,
170
+ ]), new Set([0])));
171
+ }
172
+ if (goneKeys.length > 0) {
173
+ lines.push('', '### Content that disappeared', '', markdownTable(['Count', 'Content key'], goneKeys
174
+ .slice(0, limit)
175
+ .map(([k, n]) => [
176
+ formatNumber(n),
177
+ k.length > 100 ? k.slice(0, 97) + '…' : k,
178
+ ]), new Set([0])));
179
+ }
180
+ lines.push('', `_Content equality is not object identity: two distinct objects with the same properties and values count as the same key, and one object whose contents changed between captures counts as one gone and one new. Active snapshot unchanged (${getCurrentHandle() ?? 'none'})._`);
181
+ return toolResult(lines.join('\n'));
182
+ }
183
+ catch (err) {
184
+ return errorResult(err);
185
+ }
186
+ });
187
+ }
188
+ //# sourceMappingURL=identity-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-diff.js","sourceRoot":"","sources":["../../src/tools/identity-diff.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"intern-opportunities.d.ts","sourceRoot":"","sources":["../../src/tools/intern-opportunities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAmPvE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAq8BnE"}
1
+ {"version":3,"file":"intern-opportunities.d.ts","sourceRoot":"","sources":["../../src/tools/intern-opportunities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAoPvE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAq8BnE"}
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { z } from 'zod';
11
11
  import { getSnapshot, getSnapshotMetadata, getSessionConfig, } from '../heap-state.js';
12
+ import { withAnonymizedBanner } from '../anonymized-snapshot.js';
12
13
  import { formatBytes, formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
13
14
  import { collectDevRoots, computeReachableWithoutDevRoots, } from './dev-artifacts.js';
14
15
  import { buildStringIndex } from '../string-index.js';
@@ -545,7 +546,7 @@ export function registerInternOpportunities(server) {
545
546
  .join('\n');
546
547
  msg += `\n\n⚠ However, ${formatNumber(arrayDupes.length)} value(s) are heavily duplicated (~${formatBytes(totalDup)} total) but were NOT surfaced as property groups above. This is expected when they are held as ARRAY ELEMENTS / columnar rows (e.g. a string[][] query-result buffer) rather than object properties — but it can also happen when their property groups fell below the min_copies / min_savings thresholds. If they are array elements, interning at the array-construction (parse) site collapses them; if they are properties, lower the thresholds to surface the group. Top:\n${top}\nUse memlab_search_strings to locate where each is built and confirm how it is held.`;
547
548
  }
548
- return toolResult(msg);
549
+ return toolResult(withAnonymizedBanner(snapshot, msg));
549
550
  }
550
551
  // Detect partial interning patterns (Feedback #3) and, while we're here,
551
552
  // mark which groups' savings are CROSS-load (not capturable by a per-load
@@ -876,7 +877,7 @@ export function registerInternOpportunities(server) {
876
877
  : g.parentShape;
877
878
  lines.push(`- ⚠ \`.${g.propertyName}\` on \`${shape}\` — ${formatBytes(g.savingsIfInterned)} co-retained via **${g.coRetainedVia ?? 'another structure'}**`);
878
879
  }
879
- return toolResult(lines.join('\n'));
880
+ return toolResult(withAnonymizedBanner(snapshot, lines.join('\n')));
880
881
  }
881
882
  // Co-retained groups: interning the property frees ~0 (Feedback round 4 §1).
882
883
  if (coRetainedGroups.length > 0) {
@@ -925,7 +926,7 @@ export function registerInternOpportunities(server) {
925
926
  ]
926
927
  : []));
927
928
  }
928
- return toolResult(lines.join('\n'));
929
+ return toolResult(withAnonymizedBanner(snapshot, lines.join('\n')));
929
930
  }
930
931
  catch (err) {
931
932
  return errorResult(err);