@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
@@ -34,11 +34,40 @@ import { formatNumber, markdownTable, errorResult, toolResult, } from '../utils.
34
34
  * it is written by default on every round, and anything requiring a backend
35
35
  * would not be. It is seeded from prior runs' manifests.
36
36
  */
37
- const INDEX_PATH = path.join(process.env.HOME ?? '/tmp', '.memlab-mcp', 'findings.json');
38
- function loadIndex() {
37
+ /**
38
+ * Where the index lives, most specific wins.
39
+ *
40
+ * The default is a per-machine home directory, and that default is the reason
41
+ * the tool has already produced a wrong verdict: an index with no history
42
+ * answers `check` with **NEW** for a finding that is fully documented and
43
+ * already has a fix diff. A home-dir file cannot be shared, does not survive a
44
+ * host change, and is empty on every new devserver — so the failure recurs for
45
+ * every operator rather than once.
46
+ *
47
+ * `MEMLAB_FINDINGS_INDEX` therefore points at a checked-in, shared file, and
48
+ * `workstream` scopes several of them side by side. The home-dir path is kept as
49
+ * the fallback so nothing that already works breaks.
50
+ */
51
+ export function resolveIndexPath(workstream) {
52
+ const override = process.env.MEMLAB_FINDINGS_INDEX;
53
+ if (override != null && override !== '') {
54
+ if (workstream == null || workstream === '')
55
+ return override;
56
+ // Treat the override as a directory when a workstream is named, so one
57
+ // shared location can hold several workstreams without collision.
58
+ return override.endsWith('.json')
59
+ ? override.replace(/\.json$/, `.${workstream}.json`)
60
+ : path.join(override, `findings.${workstream}.json`);
61
+ }
62
+ const base = path.join(process.env.HOME ?? '/tmp', '.memlab-mcp');
63
+ return path.join(base, workstream != null && workstream !== ''
64
+ ? `findings.${workstream}.json`
65
+ : 'findings.json');
66
+ }
67
+ function loadIndex(indexPath) {
39
68
  try {
40
- if (fs.existsSync(INDEX_PATH)) {
41
- const parsed = JSON.parse(fs.readFileSync(INDEX_PATH, 'utf8'));
69
+ if (fs.existsSync(indexPath)) {
70
+ const parsed = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
42
71
  if (parsed != null && typeof parsed === 'object') {
43
72
  const idx = parsed;
44
73
  return {
@@ -55,19 +84,78 @@ function loadIndex() {
55
84
  // the file wholesale and every prior fingerprint is gone, which defeats the
56
85
  // one thing this tool exists to do. Preserve it for recovery first.
57
86
  try {
58
- if (fs.existsSync(INDEX_PATH)) {
59
- fs.renameSync(INDEX_PATH, `${INDEX_PATH}.corrupt`);
87
+ if (fs.existsSync(indexPath)) {
88
+ fs.renameSync(indexPath, `${indexPath}.corrupt`);
60
89
  }
61
90
  }
62
91
  catch {
63
92
  // Best effort; a failed rename must not block the hunt either.
64
93
  }
65
94
  }
66
- return { version: 1, findings: {}, combos_driven: {} };
95
+ // A brand-new index is seeded with the artifact families rather than left
96
+ // empty, so the very first `check` can answer KNOWN for a population that is
97
+ // documented and is not app memory. Seeding on CREATION (not on every load)
98
+ // means a caller who deliberately removes one keeps it removed.
99
+ const fresh = { version: 1, findings: {}, combos_driven: {} };
100
+ importFindings(fresh, builtinSeedFindings());
101
+ return fresh;
67
102
  }
68
- function saveIndex(idx) {
69
- fs.mkdirSync(path.dirname(INDEX_PATH), { recursive: true });
70
- fs.writeFileSync(INDEX_PATH, JSON.stringify(idx, null, 2));
103
+ function saveIndex(indexPath, idx) {
104
+ fs.mkdirSync(path.dirname(indexPath), { recursive: true });
105
+ fs.writeFileSync(indexPath, JSON.stringify(idx, null, 2));
106
+ }
107
+ /**
108
+ * Findings accepted by `action: "import"`.
109
+ *
110
+ * Loose on purpose: the source is a hand-maintained team document or a previous
111
+ * round's notes, and rejecting a row for a missing optional field would mean the
112
+ * bootstrap does not happen at all — which is the status quo this fixes.
113
+ */
114
+ const IMPORTED_FINDING_SCHEMA = z.object({
115
+ retainer_path: z.string().optional(),
116
+ signature: z.string().optional(),
117
+ growing_classes: z.array(z.string()).optional(),
118
+ round: z.string().optional(),
119
+ status: z.enum(['new', 'known', 'fixed']).optional(),
120
+ fixed_behind: z.string().optional(),
121
+ note: z.string().optional(),
122
+ });
123
+ export function importFindings(index, incoming) {
124
+ let imported = 0;
125
+ let updated = 0;
126
+ const skipped = [];
127
+ incoming.forEach((raw, i) => {
128
+ const source = raw.retainer_path ?? raw.signature;
129
+ if (source == null || source === '') {
130
+ skipped.push(`entry ${i}: neither retainer_path nor signature`);
131
+ return;
132
+ }
133
+ // A `signature` is already normalized by definition; normalizing again is a
134
+ // no-op on well-formed input and repairs a hand-written one.
135
+ const signature = normalizeRetainerPath(source);
136
+ const classes = raw.growing_classes ?? [];
137
+ const fingerprint = fingerprintOf(signature, classes);
138
+ const existing = index.findings[fingerprint];
139
+ const round = raw.round ?? 'imported';
140
+ index.findings[fingerprint] = {
141
+ fingerprint,
142
+ signature,
143
+ growing_classes: classes,
144
+ first_seen_round: existing?.first_seen_round ?? round,
145
+ last_seen_round: round,
146
+ status: raw.status ?? existing?.status ?? 'known',
147
+ fixed_behind: raw.fixed_behind ?? existing?.fixed_behind,
148
+ note: raw.note ?? existing?.note,
149
+ // An import is history, not a sighting: it must not inflate seen_count
150
+ // for a finding this operator has never actually observed.
151
+ seen_count: existing?.seen_count ?? 1,
152
+ };
153
+ if (existing)
154
+ updated++;
155
+ else
156
+ imported++;
157
+ });
158
+ return { imported, updated, skipped };
71
159
  }
72
160
  /**
73
161
  * Normalize a retainer path into a signature that is stable across captures.
@@ -96,13 +184,149 @@ export function fingerprintOf(signature, classes) {
96
184
  const material = `${signature}||${[...classes].sort().join(',')}`;
97
185
  return crypto.createHash('sha1').update(material).digest('hex').slice(0, 12);
98
186
  }
187
+ /**
188
+ * Artifact families every hunt re-derives, seeded into a fresh index.
189
+ *
190
+ * An empty index answers NEW to everything — including populations that are
191
+ * documented, well understood, and not app memory at all. That makes the first
192
+ * `check` of a workstream actively misleading rather than merely unhelpful, and
193
+ * hand-seeding never happens because it is a step nobody is prompted to take.
194
+ *
195
+ * These entries are deliberately the GENERIC, tool-detectable families (the
196
+ * same taxonomy `artifact-classes.ts` classifies, plus the two dev-build
197
+ * registries `dev_artifacts` detects). They are marked `known` rather than
198
+ * `fixed`: they are not defects to be fixed, they are populations a hunt must
199
+ * subtract. Anything app-specific belongs in a real `action: "import"`.
200
+ */
201
+ export function builtinSeedFindings() {
202
+ const seed = (signature, growing_classes, note) => ({
203
+ signature,
204
+ growing_classes,
205
+ round: 'builtin',
206
+ status: 'known',
207
+ note,
208
+ });
209
+ return [
210
+ seed('V8 JIT/compile warmup structures', [
211
+ 'Code',
212
+ 'BytecodeArray',
213
+ 'FeedbackVector',
214
+ 'ScopeInfo',
215
+ 'InstructionStream',
216
+ ], 'Exercising new code paths during a hunt JIT-compiles them, so this family climbs every step without being an app leak. Not a finding.'),
217
+ seed('Blink accessibility cache inflated by automation', ['AXObjectCacheImpl', 'AXNodeObject', 'AXDirtyObject'], 'CDP-driven automation builds the a11y tree. These co-retain detached DOM, so retainer traces can route through them and mislead.'),
218
+ seed('CDP inspector network log', ['NetworkResourcesData', 'XHRReplayData', 'PerformanceResourceTiming'], 'Every request made while CDP is attached is retained by the DevToolsSession for the session. A dev build that polls grows this forever. Not app memory.'),
219
+ seed('CDP inspector performance timeline', ['PerformanceLongTaskTiming', 'PerformanceScriptTiming', 'LayoutShift'], 'Accumulates because something is observing it, not because the app leaks.'),
220
+ seed('CDP inspector console retention', ['ConsoleMessage'], 'Console-retained memory scales with how much the app logs, not with what it holds. A dev build logging per cycle produces a clean linear "leak" that does not exist in production.'),
221
+ seed('Captured Error stacks (React DEV owner stacks)', ['StackFrameInfo', 'ErrorStackData'], 'Usually React DEV `_debugStack` or dev-build logging capturing a stack per record. Dev-build only, but a production build can legitimately grow these — check before dismissing.'),
222
+ seed('React Fast Refresh registries (dev-only)', ['allFamiliesByID', 'allFamiliesByType', 'allSignaturesByType'], 'Dev-only hot-reload bookkeeping. The backing tables are large and sparse and V8 never shrinks an EphemeronHashTable, so they present as a big anonymous array at the top of a leak report.'),
223
+ seed('Automation/tool bridge bundle', ['(concatenated string)', '(string)'], 'The browser-automation bridge is re-evaluated per call and its source is retained per copy. Presents as many megabytes of duplicated script text that no production user ever loads.'),
224
+ ];
225
+ }
226
+ /**
227
+ * Known entries that share a growing class with the candidate.
228
+ *
229
+ * The fingerprint is an EXACT match on signature + class set, which is right for
230
+ * "have we filed this before" and useless for "is this population a known
231
+ * artifact". Measured against a freshly-seeded index: a realistic check —
232
+ * retainer path `(GC roots) > (Global handles) > Object.allSignaturesByType`,
233
+ * growing class `allSignaturesByType` — returned NEW, even though the React Fast
234
+ * Refresh registry entry naming that exact class was sitting in the index. A
235
+ * caller has to reproduce the seeded signature string verbatim to get a hit,
236
+ * which nobody will ever do, so without this the seeding is decorative.
237
+ *
238
+ * Reported ALONGSIDE the NEW verdict rather than replacing it: a class overlap
239
+ * is a lead, not an identification, and silently converting NEW to KNOWN on one
240
+ * shared class name would suppress real findings.
241
+ */
242
+ export function relatedByClass(index, classes, excludeFingerprint) {
243
+ if (classes.length === 0)
244
+ return [];
245
+ const wanted = new Set(classes);
246
+ return Object.values(index.findings)
247
+ .filter(f => f.fingerprint !== excludeFingerprint)
248
+ .map(f => ({
249
+ f,
250
+ shared: f.growing_classes.filter(c => wanted.has(c)),
251
+ }))
252
+ .filter(x => x.shared.length > 0)
253
+ .sort((a, b) => b.shared.length - a.shared.length)
254
+ .slice(0, 5)
255
+ .map(x => x.f);
256
+ }
257
+ /**
258
+ * Does the index hold anything beyond the generic built-in artifact families?
259
+ *
260
+ * `loadIndex` seeds a fresh index with those families, so a plain
261
+ * `Object.keys(findings).length === 0` is never true and every "is this index
262
+ * usable" guard built on it silently never fires. The question that actually
263
+ * matters is whether the index carries history for THIS app; built-in entries
264
+ * are stamped `first_seen_round: 'builtin'` and say nothing about it.
265
+ */
266
+ export function hasAppHistory(index) {
267
+ return Object.values(index.findings).some(f => f.first_seen_round !== 'builtin');
268
+ }
269
+ export function loadFindingIndex(workstream) {
270
+ const indexPath = resolveIndexPath(workstream);
271
+ return { index: loadIndex(indexPath), indexPath };
272
+ }
273
+ export function lookupFinding(retainerPath, classes, workstream) {
274
+ return lookupFindingIn(loadFindingIndex(workstream), retainerPath, classes);
275
+ }
276
+ export function lookupFindingIn(loaded, retainerPath, classes) {
277
+ const { index, indexPath } = loaded;
278
+ const signature = normalizeRetainerPath(retainerPath);
279
+ const classList = [...classes];
280
+ const fingerprint = fingerprintOf(signature, classList);
281
+ const hit = index.findings[fingerprint];
282
+ const indexEmpty = !hasAppHistory(index);
283
+ if (hit) {
284
+ return {
285
+ verdict: hit.status === 'fixed' ? 'KNOWN-AND-FIXED' : 'KNOWN',
286
+ fixedBehind: hit.fixed_behind,
287
+ note: hit.note,
288
+ round: hit.first_seen_round,
289
+ related: [],
290
+ indexEmpty,
291
+ indexPath,
292
+ };
293
+ }
294
+ return {
295
+ verdict: 'NEW',
296
+ related: relatedByClass(index, classList, fingerprint).map(f => `${f.growing_classes.join(', ')}${f.fixed_behind ? ` (fixed behind ${f.fixed_behind})` : ''}`),
297
+ indexEmpty,
298
+ indexPath,
299
+ };
300
+ }
301
+ /** One-line renderer for an inline verdict badge. */
302
+ export function renderFindingVerdict(l) {
303
+ if (l.verdict === 'KNOWN-AND-FIXED') {
304
+ return `\`KNOWN-AND-FIXED\`${l.fixedBehind ? ` — fixed behind \`${l.fixedBehind}\`; confirm the gate is ON in this capture before treating it as a finding` : ''}`;
305
+ }
306
+ if (l.verdict === 'KNOWN') {
307
+ return `\`KNOWN\`${l.round ? ` — first seen ${l.round}` : ''}${l.note ? `: ${l.note}` : ''}`;
308
+ }
309
+ const related = l.related.length > 0
310
+ ? ` (but shares a growing class with: ${l.related.slice(0, 2).join('; ')} — a lead, not an identification)`
311
+ : '';
312
+ return `\`NEW\`${related}`;
313
+ }
314
+ /**
315
+ * The banner to print once per report when the index cannot support a verdict.
316
+ */
317
+ export function findingIndexEmptyBanner(indexPath) {
318
+ return (`> ⚠️ **The findings index at \`${indexPath}\` is EMPTY, so every \`NEW\` below means "not in an empty list" and carries no information.** ` +
319
+ 'Seed it with `memlab_finding_index({action: "import"})` before trusting any verdict here. ' +
320
+ 'An unseeded index is how a round spends itself re-deriving a finding that was already filed and already fixed.');
321
+ }
99
322
  export function registerFindingIndex(server) {
100
323
  server.tool('memlab_finding_index', 'Fingerprint a leak finding by its retainer path and check it against findings from previous rounds, so a hunt does not spend itself re-discovering a known or already-fixed leak. ' +
101
324
  'This is the highest-cost failure a leak hunt has: a measured round produced three findings that were all already known — two already fixed behind gates — which is an entire round spent re-deriving history. Class names cannot detect that (`Object` and `Array` top every heap); the retainer PATH can, so the fingerprint is a normalized path signature with node ids, array indices and per-capture scope ids stripped. ' +
102
- 'Actions: "check" fingerprints a candidate and reports NEW / KNOWN / KNOWN-AND-FIXED; "record" adds it; "list" prints the index; "cover" records which combos a round drove, so the "do not repeat covered combos" rule stops depending on someone remembering. Stored in ~/.memlab-mcp/findings.json.', {
325
+ 'Actions: "check" fingerprints a candidate and reports NEW / KNOWN / KNOWN-AND-FIXED; "record" adds it; "import" bootstraps history in bulk from a team doc or a JSON file; "list" prints the index; "cover" records which combos a round drove, so the "do not repeat covered combos" rule stops depending on someone remembering.\n\n' +
326
+ 'IMPORTANT: a verdict of NEW is only as good as the index behind it. A newly-created index is pre-seeded with the generic ARTIFACT families (JIT warmup, CDP network/perf/console retention, a11y caches, React Fast Refresh registries, captured Error stacks, the automation bridge bundle), so the first `check` can already answer KNOWN for a population that is documented and is not app memory — but it knows nothing about YOUR app. Seed that with `action: "import"` before trusting the first `check` of a workstream. Set `MEMLAB_FINDINGS_INDEX` to a checked-in path to share the index across hosts and operators instead of keeping it in a per-machine home directory.', {
103
327
  action: z
104
- .enum(['check', 'record', 'list', 'cover'])
105
- .describe('"check" (fingerprint + look up, no write), "record" (add/update), "list", "cover" (log combos driven in a round).'),
328
+ .enum(['check', 'record', 'list', 'cover', 'import'])
329
+ .describe('"check" (fingerprint + look up, no write), "record" (add/update), "import" (bulk-seed history), "list", "cover" (log combos driven in a round).'),
106
330
  retainer_path: z
107
331
  .string()
108
332
  .optional()
@@ -134,15 +358,79 @@ export function registerFindingIndex(server) {
134
358
  .optional()
135
359
  .default([])
136
360
  .describe('For action "cover": combo names driven in this round.'),
137
- }, async ({ action, retainer_path, growing_classes, round, status, fixed_behind, note, combos, }) => {
361
+ workstream: z
362
+ .string()
363
+ .optional()
364
+ .describe('Scopes the index file, so one shared location can hold several hunts side by side (e.g. "wa-web"). Omit to use the unscoped index.'),
365
+ from: z
366
+ .string()
367
+ .optional()
368
+ .describe('For action "import": path to a JSON file holding either an array of findings or {findings: [...]}. Each entry needs retainer_path (or signature) and may carry growing_classes, round, status, fixed_behind, note.'),
369
+ findings: z
370
+ .array(IMPORTED_FINDING_SCHEMA)
371
+ .optional()
372
+ .describe('For action "import": findings passed inline, for seeding straight from a team doc without writing a file first.'),
373
+ }, async ({ action, retainer_path, growing_classes, round, status, fixed_behind, note, combos, workstream, from, findings, }) => {
138
374
  try {
139
- const index = loadIndex();
375
+ const indexPath = resolveIndexPath(workstream);
376
+ const index = loadIndex(indexPath);
377
+ if (action === 'import') {
378
+ const incoming = [...(findings ?? [])];
379
+ const fileErrors = [];
380
+ if (from != null && from !== '') {
381
+ if (!fs.existsSync(from)) {
382
+ return errorResult(`import source not found: ${from}`);
383
+ }
384
+ const parsed = JSON.parse(fs.readFileSync(from, 'utf8'));
385
+ const fromFile = Array.isArray(parsed)
386
+ ? parsed
387
+ : (parsed?.findings ?? null);
388
+ if (!Array.isArray(fromFile)) {
389
+ return errorResult(`${from} must hold a JSON array of findings, or an object with a "findings" array.`);
390
+ }
391
+ // Validate each row with the SAME schema the inline `findings`
392
+ // argument gets. A bare `as ImportedFinding[]` here let a row whose
393
+ // `growing_classes` is a string reach `fingerprintOf`, which sorts
394
+ // and joins it — producing a fingerprint no real `check` can ever
395
+ // match, and silently defeating the seeding this action exists for.
396
+ // A malformed row is reported as skipped, never cast through.
397
+ fromFile.forEach((row, i) => {
398
+ const parsedRow = IMPORTED_FINDING_SCHEMA.safeParse(row);
399
+ if (parsedRow.success) {
400
+ incoming.push(parsedRow.data);
401
+ }
402
+ else {
403
+ fileErrors.push(`${from} entry ${i}: ${parsedRow.error.issues
404
+ .map(issue => `${issue.path.join('.') || '(root)'} ${issue.message}`)
405
+ .join('; ')}`);
406
+ }
407
+ });
408
+ }
409
+ if (incoming.length === 0) {
410
+ return errorResult('action "import" needs `findings` (inline) or `from` (a JSON file path).');
411
+ }
412
+ const { imported, updated, skipped } = importFindings(index, incoming);
413
+ skipped.unshift(...fileErrors);
414
+ saveIndex(indexPath, index);
415
+ return toolResult([
416
+ `Imported **${imported} new** and updated **${updated}** finding(s) into \`${indexPath}\`; ` +
417
+ `the index now holds ${formatNumber(Object.keys(index.findings).length)}.`,
418
+ skipped.length > 0
419
+ ? `\nSkipped ${skipped.length}:\n${skipped.map(s => `- ${s}`).join('\n')}`
420
+ : '',
421
+ '\n`check` verdicts of NEW are now meaningful for anything this history covers. ' +
422
+ 'Imported entries carry `seen_count: 1` — they are history, not sightings by this operator.',
423
+ ]
424
+ .filter(Boolean)
425
+ .join('\n'));
426
+ }
140
427
  if (action === 'list') {
141
428
  const all = Object.values(index.findings);
142
- if (all.length === 0) {
143
- return toolResult('The findings index is empty. Record findings as you confirm them ' +
144
- '(`action: "record"`); the value is entirely in future rounds being ' +
145
- 'able to recognize them.');
429
+ if (!hasAppHistory(index)) {
430
+ return toolResult(`The findings index at \`${indexPath}\` is **empty**, so every \`check\` in this ` +
431
+ 'session will answer NEW including for findings that are already documented ' +
432
+ 'and already fixed. Seed it first with `action: "import"` from the workstream\'s ' +
433
+ 'history, then record findings as you confirm them (`action: "record"`).');
146
434
  }
147
435
  const rows = all
148
436
  .sort((a, b) => b.seen_count - a.seen_count)
@@ -167,7 +455,7 @@ export function registerFindingIndex(server) {
167
455
  .slice(-8)
168
456
  .map(([r, c]) => `${r}: ${c.join(', ')}`);
169
457
  return toolResult([
170
- `## Findings index (${formatNumber(all.length)})`,
458
+ `## Findings index (${formatNumber(all.length)}) — \`${indexPath}\``,
171
459
  '',
172
460
  markdownTable([
173
461
  'Fingerprint',
@@ -185,7 +473,7 @@ export function registerFindingIndex(server) {
185
473
  if (!round)
186
474
  return errorResult('action "cover" requires a round.');
187
475
  index.combos_driven[round] = combos;
188
- saveIndex(index);
476
+ saveIndex(indexPath, index);
189
477
  return toolResult(`Recorded ${combos.length} combo(s) driven in ${round}: ${combos.join(', ') || '(none)'}.`);
190
478
  }
191
479
  if (!retainer_path) {
@@ -196,13 +484,44 @@ export function registerFindingIndex(server) {
196
484
  const existing = index.findings[fingerprint];
197
485
  if (action === 'check') {
198
486
  if (!existing) {
487
+ // The single most damaging thing this tool can do is answer NEW from
488
+ // an index that has never been seeded — the verdict looks identical
489
+ // to a real one, and it has already sent a round off to re-derive a
490
+ // documented, already-fixed finding. Say so at the point of use.
491
+ const indexSize = Object.keys(index.findings).length;
492
+ const unreliable = !hasAppHistory(index)
493
+ ? [
494
+ '',
495
+ `> ⚠️ **The index at \`${indexPath}\` is EMPTY, so this verdict carries no information.** ` +
496
+ 'Every candidate reads as NEW. Seed the workstream history with ' +
497
+ '`action: "import"` before treating a NEW here as evidence of anything.',
498
+ ]
499
+ : [];
500
+ const related = relatedByClass(index, growing_classes, fingerprint);
501
+ const relatedLines = related.length === 0
502
+ ? []
503
+ : [
504
+ '',
505
+ `### ⚠️ ${related.length} known entr${related.length === 1 ? 'y shares' : 'ies share'} a growing class with this`,
506
+ '',
507
+ ...related.map(f => `- **${f.signature}** (${f.first_seen_round}, ${f.status})` +
508
+ ` — shares \`${f.growing_classes.filter(c => growing_classes.includes(c)).join('`, `')}\`` +
509
+ (f.note ? `. ${f.note}` : '')),
510
+ '',
511
+ 'A shared class is a LEAD, not an identification — the fingerprint above really is new. ' +
512
+ 'But if one of these is an artifact family, the population you are looking at is ' +
513
+ 'probably not app memory, and that is worth settling before spending the round on it.',
514
+ ];
199
515
  return toolResult([
200
516
  `## NEW finding — fingerprint \`${fingerprint}\``,
201
517
  '',
202
518
  `Signature: \`${signature}\``,
519
+ ...unreliable,
203
520
  '',
204
- 'No previous round recorded this retainer path with this class set. ' +
205
- 'Confirm it, then `action: "record"` so the next round recognizes it.',
521
+ `No previous round in this index (${formatNumber(indexSize)} finding(s)) recorded this ` +
522
+ 'retainer path with this class set. Confirm it, then `action: "record"` so the next ' +
523
+ 'round recognizes it.',
524
+ ...relatedLines,
206
525
  ].join('\n'));
207
526
  }
208
527
  const label = existing.status === 'fixed'
@@ -235,7 +554,7 @@ export function registerFindingIndex(server) {
235
554
  note: note ?? existing?.note,
236
555
  seen_count: (existing?.seen_count ?? 0) + 1,
237
556
  };
238
- saveIndex(index);
557
+ saveIndex(indexPath, index);
239
558
  return toolResult(`Recorded \`${fingerprint}\` as **${status}**${fixed_behind ? ` (behind \`${fixed_behind}\`)` : ''} for round ${roundId}. ` +
240
559
  `Signature: \`${signature}\`. The index now holds ${formatNumber(Object.keys(index.findings).length)} finding(s).`);
241
560
  }
@@ -1 +1 @@
1
- {"version":3,"file":"finding-index.js","sourceRoot":"","sources":["../../src/tools/finding-index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"finding-index.js","sourceRoot":"","sources":["../../src/tools/finding-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAmB;IAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACnD,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACxC,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,KAAK,EAAE;YAAE,OAAO,QAAQ,CAAC;QAC7D,uEAAuE;QACvE,kEAAkE;QAClE,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,UAAU,OAAO,CAAC;YACpD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,UAAU,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,aAAa,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC,IAAI,CACd,IAAI,EACJ,UAAU,IAAI,IAAI,IAAI,UAAU,KAAK,EAAE;QACrC,CAAC,CAAC,YAAY,UAAU,OAAO;QAC/B,CAAC,CAAC,eAAe,CACpB,CAAC;AACJ,CAAC;AAoBD,SAAS,SAAS,CAAC,SAAiB;IAClC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;YACvE,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACjD,MAAM,GAAG,GAAG,MAA+B,CAAC;gBAC5C,OAAO;oBACL,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,CAAC;oBACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;oBAC5B,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE;iBACvC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;QACtE,yEAAyE;QACzE,4EAA4E;QAC5E,oEAAoE;QACpE,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,SAAS,UAAU,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;QACjE,CAAC;IACH,CAAC;IACD,0EAA0E;IAC1E,6EAA6E;IAC7E,4EAA4E;IAC5E,gEAAgE;IAChE,MAAM,KAAK,GAAiB,EAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAC,CAAC;IAC1E,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,SAAiB,EAAE,GAAiB;IACrD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IACzD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAIH,MAAM,UAAU,cAAc,CAC5B,KAAmB,EACnB,QAA2B;IAE3B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,SAAS,CAAC;QAClD,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QACD,4EAA4E;QAC5E,6DAA6D;QAC7D,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;QAC1C,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,UAAU,CAAC;QACtC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG;YAC5B,WAAW;YACX,SAAS;YACT,eAAe,EAAE,OAAO;YACxB,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,IAAI,KAAK;YACrD,eAAe,EAAE,KAAK;YACtB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,QAAQ,EAAE,MAAM,IAAI,OAAO;YACjD,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,QAAQ,EAAE,YAAY;YACxD,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,QAAQ,EAAE,IAAI;YAChC,uEAAuE;YACvE,2DAA2D;YAC3D,UAAU,EAAE,QAAQ,EAAE,UAAU,IAAI,CAAC;SACtC,CAAC;QACF,IAAI,QAAQ;YAAE,OAAO,EAAE,CAAC;;YACnB,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,CACL,GAAG;SACA,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;QAC3B,uEAAuE;QACvE,4EAA4E;QAC5E,wEAAwE;SACvE,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC;SAClC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,sBAAsB,EAAE,KAAK,CAAC;QACvC,6EAA6E;SAC5E,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC;SAC3B,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAiB;IAChE,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClE,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,IAAI,GAAG,CACX,SAAiB,EACjB,eAAyB,EACzB,IAAY,EACK,EAAE,CAAC,CAAC;QACrB,SAAS;QACT,eAAe;QACf,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,OAAO;QACf,IAAI;KACL,CAAC,CAAC;IACH,OAAO;QACL,IAAI,CACF,kCAAkC,EAClC;YACE,MAAM;YACN,eAAe;YACf,gBAAgB;YAChB,WAAW;YACX,mBAAmB;SACpB,EACD,uIAAuI,CACxI;QACD,IAAI,CACF,kDAAkD,EAClD,CAAC,mBAAmB,EAAE,cAAc,EAAE,eAAe,CAAC,EACtD,kIAAkI,CACnI;QACD,IAAI,CACF,2BAA2B,EAC3B,CAAC,sBAAsB,EAAE,eAAe,EAAE,2BAA2B,CAAC,EACtE,yJAAyJ,CAC1J;QACD,IAAI,CACF,oCAAoC,EACpC,CAAC,2BAA2B,EAAE,yBAAyB,EAAE,aAAa,CAAC,EACvE,2EAA2E,CAC5E;QACD,IAAI,CACF,iCAAiC,EACjC,CAAC,gBAAgB,CAAC,EAClB,oLAAoL,CACrL;QACD,IAAI,CACF,gDAAgD,EAChD,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,EACpC,kLAAkL,CACnL;QACD,IAAI,CACF,0CAA0C,EAC1C,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,qBAAqB,CAAC,EAC/D,4LAA4L,CAC7L;QACD,IAAI,CACF,+BAA+B,EAC/B,CAAC,uBAAuB,EAAE,UAAU,CAAC,EACrC,sLAAsL,CACvL;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAmB,EACnB,OAA0B,EAC1B,kBAA0B;IAE1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,kBAAkB,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,CAAC;QACD,MAAM,EAAE,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KACrD,CAAC,CAAC;SACF,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;SACjD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAE7B;IACC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,SAAS,CACtC,CAAC;AACJ,CAAC;AAqCD,MAAM,UAAU,gBAAgB,CAAC,UAAmB;IAClD,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC/C,OAAO,EAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS,EAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,YAAoB,EACpB,OAA0B,EAC1B,UAAmB;IAEnB,OAAO,eAAe,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAA0B,EAC1B,YAAoB,EACpB,OAA0B;IAE1B,MAAM,EAAC,KAAK,EAAE,SAAS,EAAC,GAAG,MAAM,CAAC;IAClC,MAAM,SAAS,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC/B,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO;YACL,OAAO,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO;YAC7D,WAAW,EAAE,GAAG,CAAC,YAAY;YAC7B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,gBAAgB;YAC3B,OAAO,EAAE,EAAE;YACX,UAAU;YACV,SAAS;SACV,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,CACxD,CAAC,CAAC,EAAE,CACF,GAAG,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChG;QACD,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,oBAAoB,CAAC,CAAgB;IACnD,IAAI,CAAC,CAAC,OAAO,KAAK,iBAAiB,EAAE,CAAC;QACpC,OAAO,sBAAsB,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,WAAW,4EAA4E,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACrK,CAAC;IACD,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC/F,CAAC;IACD,MAAM,OAAO,GACX,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAClB,CAAC,CAAC,sCAAsC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC;QAC3G,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,UAAU,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACvD,OAAO,CACL,kCAAkC,SAAS,iGAAiG;QAC5I,4FAA4F;QAC5F,gHAAgH,CACjH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,oLAAoL;QAClL,gaAAga;QACha,wUAAwU;QACxU,ypBAAypB,EAC3pB;QACE,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;aACpD,QAAQ,CACP,iJAAiJ,CAClJ;QACH,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,4HAA4H,CAC7H;QACH,eAAe,EAAE,CAAC;aACf,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CACP,0JAA0J,CAC3J;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,6DAA6D,CAC9D;QACH,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;aAC/B,QAAQ,EAAE;aACV,OAAO,CAAC,OAAO,CAAC;aAChB,QAAQ,CAAC,2DAA2D,CAAC;QACxE,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yCAAyC,CAAC;QACtD,MAAM,EAAE,CAAC;aACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,uDAAuD,CAAC;QACpE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,oIAAoI,CACrI;QACH,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,oNAAoN,CACrN;QACH,QAAQ,EAAE,CAAC;aACR,KAAK,CAAC,uBAAuB,CAAC;aAC9B,QAAQ,EAAE;aACV,QAAQ,CACP,iHAAiH,CAClH;KACJ,EACD,KAAK,EAAE,EACL,MAAM,EACN,aAAa,EACb,eAAe,EACf,KAAK,EACL,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,MAAM,EACN,UAAU,EACV,IAAI,EACJ,QAAQ,GACT,EAAE,EAAE;QACH,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;YAEnC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAsB,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC1D,MAAM,UAAU,GAAa,EAAE,CAAC;gBAChC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;oBAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;wBACzB,OAAO,WAAW,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;oBACzD,CAAC;oBACD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;wBACpC,CAAC,CAAC,MAAM;wBACR,CAAC,CAAC,CAAE,MAAiC,EAAE,QAAQ,IAAI,IAAI,CAAC,CAAC;oBAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC7B,OAAO,WAAW,CAChB,GAAG,IAAI,4EAA4E,CACpF,CAAC;oBACJ,CAAC;oBACD,+DAA+D;oBAC/D,oEAAoE;oBACpE,mEAAmE;oBACnE,kEAAkE;oBAClE,oEAAoE;oBACpE,8DAA8D;oBAC9D,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;wBAC1B,MAAM,SAAS,GAAG,uBAAuB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;wBACzD,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;4BACtB,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;wBAChC,CAAC;6BAAM,CAAC;4BACN,UAAU,CAAC,IAAI,CACb,GAAG,IAAI,UAAU,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,MAAM;iCAC1C,GAAG,CACF,KAAK,CAAC,EAAE,CACN,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,CACzD;iCACA,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;wBACJ,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,OAAO,WAAW,CAChB,yEAAyE,CAC1E,CAAC;gBACJ,CAAC;gBACD,MAAM,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAC,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACrE,OAAO,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC;gBAC/B,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC5B,OAAO,UAAU,CACf;oBACE,cAAc,QAAQ,wBAAwB,OAAO,wBAAwB,SAAS,MAAM;wBAC1F,uBAAuB,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG;oBAC5E,OAAO,CAAC,MAAM,GAAG,CAAC;wBAChB,CAAC,CAAC,aAAa,OAAO,CAAC,MAAM,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;wBAC1E,CAAC,CAAC,EAAE;oBACN,iFAAiF;wBAC/E,4FAA4F;iBAC/F;qBACE,MAAM,CAAC,OAAO,CAAC;qBACf,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC1C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1B,OAAO,UAAU,CACf,2BAA2B,SAAS,8CAA8C;wBAChF,+EAA+E;wBAC/E,kFAAkF;wBAClF,yEAAyE,CAC5E,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,GAAG,GAAG;qBACb,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;qBAC3C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;qBACZ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBACR,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,MAAM,KAAK,OAAO;wBAClB,CAAC,CAAC,UAAU,CAAC,CAAC,YAAY,IAAI,GAAG,GAAG;wBACpC,CAAC,CAAC,CAAC,CAAC,MAAM;oBACZ,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG;oBAC/C,GAAG,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,eAAe,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;oBACjG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;oBACpB,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,EAAE;wBACrB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;wBAChC,CAAC,CAAC,CAAC,CAAC,SAAS;iBAChB,CAAC,CAAC;gBACL,kEAAkE;gBAClE,kEAAkE;gBAClE,sCAAsC;gBACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;qBAChD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CACrD;qBACA,KAAK,CAAC,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC5C,OAAO,UAAU,CACf;oBACE,sBAAsB,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,SAAS,IAAI;oBACpE,EAAE;oBACF,aAAa,CACX;wBACE,aAAa;wBACb,QAAQ;wBACR,SAAS;wBACT,QAAQ;wBACR,MAAM;wBACN,WAAW;qBACZ,EACD,IAAI,EACJ,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CACb;oBACD,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE;oBAC3D,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;iBAC9B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,KAAK;oBAAE,OAAO,WAAW,CAAC,kCAAkC,CAAC,CAAC;gBACnE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;gBACpC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC5B,OAAO,UAAU,CACf,YAAY,MAAM,CAAC,MAAM,uBAAuB,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,CAC3F,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO,WAAW,CAAC,WAAW,MAAM,6BAA6B,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,SAAS,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAE7C,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,qEAAqE;oBACrE,oEAAoE;oBACpE,oEAAoE;oBACpE,iEAAiE;oBACjE,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;oBACrD,MAAM,UAAU,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC;wBACtC,CAAC,CAAC;4BACE,EAAE;4BACF,yBAAyB,SAAS,yDAAyD;gCACzF,iEAAiE;gCACjE,wEAAwE;yBAC3E;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;oBACpE,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,KAAK,CAAC;wBAClB,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC;4BACE,EAAE;4BACF,UAAU,OAAO,CAAC,MAAM,cAAc,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,4BAA4B;4BACjH,EAAE;4BACF,GAAG,OAAO,CAAC,GAAG,CACZ,CAAC,CAAC,EAAE,CACF,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,gBAAgB,KAAK,CAAC,CAAC,MAAM,GAAG;gCAC3D,eAAe,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;gCAC1F,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAChC;4BACD,EAAE;4BACF,yFAAyF;gCACvF,kFAAkF;gCAClF,sFAAsF;yBACzF,CAAC;oBACR,OAAO,UAAU,CACf;wBACE,kCAAkC,WAAW,IAAI;wBACjD,EAAE;wBACF,gBAAgB,SAAS,IAAI;wBAC7B,GAAG,UAAU;wBACb,EAAE;wBACF,oCAAoC,YAAY,CAAC,SAAS,CAAC,6BAA6B;4BACtF,qFAAqF;4BACrF,sBAAsB;wBACxB,GAAG,YAAY;qBAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;gBACJ,CAAC;gBACD,MAAM,KAAK,GACT,QAAQ,CAAC,MAAM,KAAK,OAAO;oBACzB,CAAC,CAAC,0BAA0B,QAAQ,CAAC,YAAY,IAAI,cAAc,GAAG;oBACtE,CAAC,CAAC,UAAU,QAAQ,CAAC,gBAAgB,GAAG,CAAC;gBAC7C,OAAO,UAAU,CACf;oBACE,MAAM,KAAK,oBAAoB,WAAW,IAAI;oBAC9C,EAAE;oBACF,gBAAgB,SAAS,IAAI;oBAC7B,eAAe,QAAQ,CAAC,gBAAgB,gBAAgB,QAAQ,CAAC,eAAe,UAAU,QAAQ,CAAC,UAAU,IAAI;oBACjH,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;oBAC7C,EAAE;oBACF,QAAQ,CAAC,MAAM,KAAK,OAAO;wBACzB,CAAC,CAAC,sDAAsD,QAAQ,CAAC,YAAY,yIAAyI;wBACtN,CAAC,CAAC,mIAAmI;iBACxI;qBACE,MAAM,CAAC,OAAO,CAAC;qBACf,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;YACJ,CAAC;YAED,SAAS;YACT,MAAM,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC;YACnC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG;gBAC5B,WAAW;gBACX,SAAS;gBACT,eAAe;gBACf,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,IAAI,OAAO;gBACvD,eAAe,EAAE,OAAO;gBACxB,MAAM;gBACN,YAAY,EAAE,YAAY,IAAI,QAAQ,EAAE,YAAY;gBACpD,IAAI,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI;gBAC5B,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC;aAC5C,CAAC;YACF,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5B,OAAO,UAAU,CACf,cAAc,WAAW,WAAW,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,cAAc,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,cAAc,OAAO,IAAI;gBACzH,gBAAgB,SAAS,2BAA2B,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,cAAc,CACrH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -8,5 +8,21 @@
8
8
  * @oncall memory_lab
9
9
  */
10
10
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ import type { IHeapNode, IHeapSnapshot } from '@memlab/core';
12
+ export declare function decodeSmi(node: IHeapNode): number | null;
13
+ export interface SmiCalibration {
14
+ checked: number;
15
+ agreed: number;
16
+ verdict: 'holds' | 'fails' | 'unknown';
17
+ }
18
+ /**
19
+ * Self-check the `id >> 1` identity against ground truth available inside the
20
+ * same snapshot: an Array's `length` property is a SMI whose value must equal
21
+ * the number of element edges on that array. If the decode reproduces the real
22
+ * length on several independent arrays, it holds for this capture; if it does
23
+ * not, every decoded SMI in this snapshot is suspect and the tool should say so
24
+ * instead of printing a number.
25
+ */
26
+ export declare function calibrateSmiDecode(snapshot: IHeapSnapshot, sampleSize?: number): SmiCalibration;
11
27
  export declare function registerGetValue(server: McpServer): void;
12
28
  //# sourceMappingURL=get-value.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-value.d.ts","sourceRoot":"","sources":["../../src/tools/get-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA4EvE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmIxD"}
1
+ {"version":3,"file":"get-value.d.ts","sourceRoot":"","sources":["../../src/tools/get-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AAW3D,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAexD;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,UAAU,SAAK,GACd,cAAc,CA+BhB;AAmFD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwJxD"}
@@ -10,15 +10,94 @@
10
10
  import { z } from 'zod';
11
11
  import { getSnapshot } from '../heap-state.js';
12
12
  import { formatBytes, formatNodeInline, errorResult, toolResult, suggestionsSuppressed, } from '../utils.js';
13
- function decodeSmi(node) {
13
+ export function decodeSmi(node) {
14
14
  // V8 stores Small Integers (SMIs) with the value encoded in the node ID.
15
15
  // SMI node IDs are odd numbers; the actual value is id >> 1.
16
16
  // SMI nodes have type "number" and name "smi number" with self_size 0.
17
+ //
18
+ // This identity is a heuristic, not a guarantee: it holds only when the
19
+ // capture assigns SMI node ids that way, and a snapshot can also contain a
20
+ // SHARED smi node that many unrelated properties point at, in which case no
21
+ // single decoded number can be right for all of them. Both cases are
22
+ // detected below (calibrateSmiDecode / sharedSmiWarning) rather than
23
+ // reporting a confident wrong integer.
17
24
  if (node.name === 'smi number' && node.self_size === 0) {
18
25
  return node.id >> 1;
19
26
  }
20
27
  return null;
21
28
  }
29
+ /**
30
+ * Self-check the `id >> 1` identity against ground truth available inside the
31
+ * same snapshot: an Array's `length` property is a SMI whose value must equal
32
+ * the number of element edges on that array. If the decode reproduces the real
33
+ * length on several independent arrays, it holds for this capture; if it does
34
+ * not, every decoded SMI in this snapshot is suspect and the tool should say so
35
+ * instead of printing a number.
36
+ */
37
+ export function calibrateSmiDecode(snapshot, sampleSize = 25) {
38
+ let checked = 0;
39
+ let agreed = 0;
40
+ snapshot.nodes.forEach(node => {
41
+ if (checked >= sampleSize)
42
+ return;
43
+ if (node.type !== 'object' || node.name !== 'Array')
44
+ return;
45
+ let lengthNode = null;
46
+ let elements = 0;
47
+ for (const edge of node.references) {
48
+ if (edge.type === 'element')
49
+ elements++;
50
+ else if (edge.type === 'property' &&
51
+ String(edge.name_or_index) === 'length') {
52
+ lengthNode = edge.toNode;
53
+ }
54
+ }
55
+ if (lengthNode == null)
56
+ return;
57
+ const decoded = decodeSmi(lengthNode);
58
+ if (decoded == null)
59
+ return;
60
+ checked++;
61
+ if (decoded === elements)
62
+ agreed++;
63
+ });
64
+ if (checked === 0)
65
+ return { checked: 0, agreed: 0, verdict: 'unknown' };
66
+ // Arrays with holes or non-element storage legitimately disagree, so require
67
+ // a clear majority rather than unanimity before trusting the identity.
68
+ return {
69
+ checked,
70
+ agreed,
71
+ verdict: agreed / checked >= 0.6 ? 'holds' : 'fails',
72
+ };
73
+ }
74
+ /**
75
+ * A smi node reachable from several differently-named properties is SHARED —
76
+ * one integer cannot be the value of all of them, so the decode is describing
77
+ * the node, not the property the caller asked about.
78
+ */
79
+ function sharedSmiWarning(node) {
80
+ const names = new Set();
81
+ let referrers = 0;
82
+ for (const edge of node.referrers) {
83
+ referrers++;
84
+ if (edge.type === 'property')
85
+ names.add(String(edge.name_or_index));
86
+ if (referrers > 50)
87
+ break;
88
+ }
89
+ if (referrers <= 1)
90
+ return null;
91
+ const sample = [...names]
92
+ .slice(0, 6)
93
+ .map(n => `\`${n}\``)
94
+ .join(', ');
95
+ return (`This node has ${referrers > 50 ? '50+' : referrers} referrers` +
96
+ (names.size > 1
97
+ ? ` under ${names.size} different property names (${sample}${names.size > 6 ? ', …' : ''})`
98
+ : '') +
99
+ '. A shared SMI node cannot hold a distinct value for each of them, so treat the decode as a property OF THE NODE, not as the value of the property you looked up.');
100
+ }
22
101
  function decodeHeapNumber(node) {
23
102
  // V8 stores heap numbers (doubles that don't fit in SMI range) as
24
103
  // separate heap objects. The actual IEEE 754 value is not directly
@@ -95,8 +174,23 @@ export function registerGetValue(server) {
95
174
  lines.push('');
96
175
  const smiValue = decodeSmi(node);
97
176
  if (smiValue !== null) {
98
- lines.push(`**Decoded SMI Value:** ${smiValue}`);
177
+ const calibration = calibrateSmiDecode(snapshot);
178
+ const shared = sharedSmiWarning(node);
179
+ const trustworthy = calibration.verdict === 'holds' && shared == null;
180
+ lines.push(`**Decoded SMI Value:** ${smiValue}${trustworthy ? '' : ' ⚠ UNVERIFIED'}`);
99
181
  lines.push(`**Encoding:** SMI (Small Integer) — value = node_id >> 1 = ${node.id} >> 1 = ${smiValue}`);
182
+ if (calibration.verdict === 'holds') {
183
+ lines.push(`**Decode self-check:** the identity reproduced the true element count on ${calibration.agreed}/${calibration.checked} sampled arrays, so it holds for this capture.`);
184
+ }
185
+ else if (calibration.verdict === 'fails') {
186
+ lines.push(`**⚠ Decode self-check FAILED:** on this capture \`id >> 1\` reproduced the true \`length\` on only ${calibration.agreed}/${calibration.checked} sampled arrays. The number above is very likely wrong — do not quote it. Read the value from a source that does not depend on the identity (the owning object via \`memlab_object_shape\`, or the application's own logging).`);
187
+ }
188
+ else {
189
+ lines.push('**Decode self-check:** could not run (no sampled array carried a SMI `length`), so the identity is unverified on this capture.');
190
+ }
191
+ if (shared != null) {
192
+ lines.push(`**⚠ Shared node:** ${shared}`);
193
+ }
100
194
  }
101
195
  else {
102
196
  const heapNum = decodeHeapNumber(node);