@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.
- package/README.md +22 -2
- package/dist/anonymized-snapshot.d.ts +75 -0
- package/dist/anonymized-snapshot.d.ts.map +1 -0
- package/dist/anonymized-snapshot.js +101 -0
- package/dist/anonymized-snapshot.js.map +1 -0
- package/dist/eval-hints.d.ts +41 -0
- package/dist/eval-hints.d.ts.map +1 -0
- package/dist/eval-hints.js +115 -0
- package/dist/eval-hints.js.map +1 -0
- package/dist/heap-budget.d.ts +32 -0
- package/dist/heap-budget.d.ts.map +1 -0
- package/dist/heap-budget.js +90 -0
- package/dist/heap-budget.js.map +1 -0
- package/dist/heap-shapes.d.ts +148 -0
- package/dist/heap-shapes.d.ts.map +1 -0
- package/dist/heap-shapes.js +193 -0
- package/dist/heap-shapes.js.map +1 -0
- package/dist/heap-state.d.ts +20 -0
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +8 -1
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/dist/react-shapes.d.ts +42 -0
- package/dist/react-shapes.d.ts.map +1 -0
- package/dist/react-shapes.js +149 -0
- package/dist/react-shapes.js.map +1 -0
- package/dist/server-version.d.ts +19 -0
- package/dist/server-version.d.ts.map +1 -0
- package/dist/server-version.js +19 -0
- package/dist/server-version.js.map +1 -0
- package/dist/snapshot-borrow.d.ts +67 -0
- package/dist/snapshot-borrow.d.ts.map +1 -0
- package/dist/snapshot-borrow.js +113 -0
- package/dist/snapshot-borrow.js.map +1 -0
- package/dist/string-index.d.ts.map +1 -1
- package/dist/string-index.js +8 -0
- package/dist/string-index.js.map +1 -1
- package/dist/tools/analyze-run.d.ts.map +1 -1
- package/dist/tools/analyze-run.js +79 -18
- package/dist/tools/analyze-run.js.map +1 -1
- package/dist/tools/anonymize-snapshot.d.ts +12 -0
- package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
- package/dist/tools/anonymize-snapshot.js +159 -0
- package/dist/tools/anonymize-snapshot.js.map +1 -0
- package/dist/tools/app-config.d.ts +12 -0
- package/dist/tools/app-config.d.ts.map +1 -0
- package/dist/tools/app-config.js +217 -0
- package/dist/tools/app-config.js.map +1 -0
- package/dist/tools/app-heap.d.ts +18 -0
- package/dist/tools/app-heap.d.ts.map +1 -1
- package/dist/tools/app-heap.js +12 -46
- package/dist/tools/app-heap.js.map +1 -1
- package/dist/tools/artifact-budget.d.ts +12 -0
- package/dist/tools/artifact-budget.d.ts.map +1 -0
- package/dist/tools/artifact-budget.js +219 -0
- package/dist/tools/artifact-budget.js.map +1 -0
- package/dist/tools/async-census.d.ts +12 -0
- package/dist/tools/async-census.d.ts.map +1 -0
- package/dist/tools/async-census.js +243 -0
- package/dist/tools/async-census.js.map +1 -0
- package/dist/tools/auto-investigate.d.ts.map +1 -1
- package/dist/tools/auto-investigate.js +54 -5
- package/dist/tools/auto-investigate.js.map +1 -1
- package/dist/tools/batch.d.ts.map +1 -1
- package/dist/tools/batch.js +33 -5
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/cache-analysis.d.ts +15 -0
- package/dist/tools/cache-analysis.d.ts.map +1 -1
- package/dist/tools/cache-analysis.js +85 -10
- package/dist/tools/cache-analysis.js.map +1 -1
- package/dist/tools/census-diff.d.ts +55 -0
- package/dist/tools/census-diff.d.ts.map +1 -0
- package/dist/tools/census-diff.js +228 -0
- package/dist/tools/census-diff.js.map +1 -0
- package/dist/tools/chain-walk.d.ts +12 -0
- package/dist/tools/chain-walk.d.ts.map +1 -0
- package/dist/tools/chain-walk.js +184 -0
- package/dist/tools/chain-walk.js.map +1 -0
- package/dist/tools/collection-diff.d.ts +44 -0
- package/dist/tools/collection-diff.d.ts.map +1 -0
- package/dist/tools/collection-diff.js +343 -0
- package/dist/tools/collection-diff.js.map +1 -0
- package/dist/tools/collection-trend.d.ts.map +1 -1
- package/dist/tools/collection-trend.js +2 -2
- package/dist/tools/collection-trend.js.map +1 -1
- package/dist/tools/detached-dom.d.ts +3 -0
- package/dist/tools/detached-dom.d.ts.map +1 -1
- package/dist/tools/detached-dom.js +78 -3
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/dev-artifacts.d.ts.map +1 -1
- package/dist/tools/dev-artifacts.js +221 -3
- package/dist/tools/dev-artifacts.js.map +1 -1
- package/dist/tools/diff-snapshots.d.ts.map +1 -1
- package/dist/tools/diff-snapshots.js +18 -2
- package/dist/tools/diff-snapshots.js.map +1 -1
- package/dist/tools/dom-audit.d.ts +37 -0
- package/dist/tools/dom-audit.d.ts.map +1 -0
- package/dist/tools/dom-audit.js +247 -0
- package/dist/tools/dom-audit.js.map +1 -0
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +3 -2
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval-across.d.ts +12 -0
- package/dist/tools/eval-across.d.ts.map +1 -0
- package/dist/tools/eval-across.js +135 -0
- package/dist/tools/eval-across.js.map +1 -0
- package/dist/tools/eval.d.ts +78 -0
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +2270 -701
- package/dist/tools/eval.js.map +1 -1
- package/dist/tools/event-listener-leaks.d.ts.map +1 -1
- package/dist/tools/event-listener-leaks.js +42 -17
- package/dist/tools/event-listener-leaks.js.map +1 -1
- package/dist/tools/event-registry.d.ts.map +1 -1
- package/dist/tools/event-registry.js +42 -8
- package/dist/tools/event-registry.js.map +1 -1
- package/dist/tools/explain-delta.d.ts.map +1 -1
- package/dist/tools/explain-delta.js +61 -10
- package/dist/tools/explain-delta.js.map +1 -1
- package/dist/tools/finding-index.d.ts +181 -0
- package/dist/tools/finding-index.d.ts.map +1 -1
- package/dist/tools/finding-index.js +343 -24
- package/dist/tools/finding-index.js.map +1 -1
- package/dist/tools/get-value.d.ts +16 -0
- package/dist/tools/get-value.d.ts.map +1 -1
- package/dist/tools/get-value.js +96 -2
- package/dist/tools/get-value.js.map +1 -1
- package/dist/tools/hypothesis.d.ts.map +1 -1
- package/dist/tools/hypothesis.js +117 -58
- package/dist/tools/hypothesis.js.map +1 -1
- package/dist/tools/id-space-audit.d.ts +12 -0
- package/dist/tools/id-space-audit.d.ts.map +1 -0
- package/dist/tools/id-space-audit.js +262 -0
- package/dist/tools/id-space-audit.js.map +1 -0
- package/dist/tools/identify.d.ts +12 -0
- package/dist/tools/identify.d.ts.map +1 -0
- package/dist/tools/identify.js +205 -0
- package/dist/tools/identify.js.map +1 -0
- package/dist/tools/identity-diff.d.ts +12 -0
- package/dist/tools/identity-diff.d.ts.map +1 -0
- package/dist/tools/identity-diff.js +188 -0
- package/dist/tools/identity-diff.js.map +1 -0
- package/dist/tools/intern-opportunities.d.ts.map +1 -1
- package/dist/tools/intern-opportunities.js +4 -3
- package/dist/tools/intern-opportunities.js.map +1 -1
- package/dist/tools/ladder-probe.d.ts +65 -0
- package/dist/tools/ladder-probe.d.ts.map +1 -0
- package/dist/tools/ladder-probe.js +445 -0
- package/dist/tools/ladder-probe.js.map +1 -0
- package/dist/tools/ladder.d.ts.map +1 -1
- package/dist/tools/ladder.js +5 -5
- package/dist/tools/ladder.js.map +1 -1
- package/dist/tools/leak-report.d.ts +23 -0
- package/dist/tools/leak-report.d.ts.map +1 -1
- package/dist/tools/leak-report.js +153 -11
- package/dist/tools/leak-report.js.map +1 -1
- package/dist/tools/load-snapshot.d.ts +11 -0
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +83 -10
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/metric.d.ts +13 -0
- package/dist/tools/metric.d.ts.map +1 -0
- package/dist/tools/metric.js +185 -0
- package/dist/tools/metric.js.map +1 -0
- package/dist/tools/module-attribution.d.ts +36 -0
- package/dist/tools/module-attribution.d.ts.map +1 -0
- package/dist/tools/module-attribution.js +235 -0
- package/dist/tools/module-attribution.js.map +1 -0
- package/dist/tools/next-measurement.d.ts +26 -0
- package/dist/tools/next-measurement.d.ts.map +1 -0
- package/dist/tools/next-measurement.js +149 -0
- package/dist/tools/next-measurement.js.map +1 -0
- package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
- package/dist/tools/object-cost-breakdown.js +64 -0
- package/dist/tools/object-cost-breakdown.js.map +1 -1
- package/dist/tools/population-vs-owners.d.ts +12 -0
- package/dist/tools/population-vs-owners.d.ts.map +1 -0
- package/dist/tools/population-vs-owners.js +183 -0
- package/dist/tools/population-vs-owners.js.map +1 -0
- package/dist/tools/property-names.d.ts +29 -0
- package/dist/tools/property-names.d.ts.map +1 -0
- package/dist/tools/property-names.js +131 -0
- package/dist/tools/property-names.js.map +1 -0
- package/dist/tools/quick-diagnosis.d.ts.map +1 -1
- package/dist/tools/quick-diagnosis.js +7 -1
- package/dist/tools/quick-diagnosis.js.map +1 -1
- package/dist/tools/react-owners.d.ts +12 -0
- package/dist/tools/react-owners.d.ts.map +1 -0
- package/dist/tools/react-owners.js +167 -0
- package/dist/tools/react-owners.js.map +1 -0
- package/dist/tools/react-update-queues.d.ts +12 -0
- package/dist/tools/react-update-queues.d.ts.map +1 -0
- package/dist/tools/react-update-queues.js +173 -0
- package/dist/tools/react-update-queues.js.map +1 -0
- package/dist/tools/replicate.d.ts +49 -0
- package/dist/tools/replicate.d.ts.map +1 -0
- package/dist/tools/replicate.js +241 -0
- package/dist/tools/replicate.js.map +1 -0
- package/dist/tools/retainer-diff.d.ts +12 -0
- package/dist/tools/retainer-diff.d.ts.map +1 -0
- package/dist/tools/retainer-diff.js +168 -0
- package/dist/tools/retainer-diff.js.map +1 -0
- package/dist/tools/retainer-summary.d.ts +17 -0
- package/dist/tools/retainer-summary.d.ts.map +1 -1
- package/dist/tools/retainer-summary.js +85 -22
- package/dist/tools/retainer-summary.js.map +1 -1
- package/dist/tools/retainer-trace.d.ts.map +1 -1
- package/dist/tools/retainer-trace.js +11 -1
- package/dist/tools/retainer-trace.js.map +1 -1
- package/dist/tools/round-audit.d.ts +66 -0
- package/dist/tools/round-audit.d.ts.map +1 -0
- package/dist/tools/round-audit.js +258 -0
- package/dist/tools/round-audit.js.map +1 -0
- package/dist/tools/round-digest.d.ts +12 -0
- package/dist/tools/round-digest.d.ts.map +1 -0
- package/dist/tools/round-digest.js +190 -0
- package/dist/tools/round-digest.js.map +1 -0
- package/dist/tools/script-census.d.ts +12 -0
- package/dist/tools/script-census.d.ts.map +1 -0
- package/dist/tools/script-census.js +182 -0
- package/dist/tools/script-census.js.map +1 -0
- package/dist/tools/sequence-analysis.d.ts +4 -0
- package/dist/tools/sequence-analysis.d.ts.map +1 -1
- package/dist/tools/sequence-analysis.js +53 -9
- package/dist/tools/sequence-analysis.js.map +1 -1
- package/dist/tools/server-status.d.ts.map +1 -1
- package/dist/tools/server-status.js +4 -1
- package/dist/tools/server-status.js.map +1 -1
- package/dist/tools/settle-check.d.ts +12 -0
- package/dist/tools/settle-check.d.ts.map +1 -0
- package/dist/tools/settle-check.js +188 -0
- package/dist/tools/settle-check.js.map +1 -0
- package/dist/tools/sliced-strings.d.ts.map +1 -1
- package/dist/tools/sliced-strings.js +2 -1
- package/dist/tools/sliced-strings.js.map +1 -1
- package/dist/tools/snapshots.d.ts.map +1 -1
- package/dist/tools/snapshots.js +24 -6
- package/dist/tools/snapshots.js.map +1 -1
- package/dist/tools/sparse-elements.d.ts +12 -0
- package/dist/tools/sparse-elements.d.ts.map +1 -0
- package/dist/tools/sparse-elements.js +215 -0
- package/dist/tools/sparse-elements.js.map +1 -0
- package/dist/tools/stale-collections.d.ts +17 -0
- package/dist/tools/stale-collections.d.ts.map +1 -1
- package/dist/tools/stale-collections.js +28 -0
- package/dist/tools/stale-collections.js.map +1 -1
- package/dist/tools/string-patterns.d.ts.map +1 -1
- package/dist/tools/string-patterns.js +2 -1
- package/dist/tools/string-patterns.js.map +1 -1
- package/dist/tools/tools-index.d.ts.map +1 -1
- package/dist/tools/tools-index.js +155 -5
- package/dist/tools/tools-index.js.map +1 -1
- package/dist/tools/trace-all.d.ts +42 -0
- package/dist/tools/trace-all.d.ts.map +1 -0
- package/dist/tools/trace-all.js +263 -0
- package/dist/tools/trace-all.js.map +1 -0
- package/dist/tools/unit-cost.d.ts +12 -0
- package/dist/tools/unit-cost.d.ts.map +1 -0
- package/dist/tools/unit-cost.js +219 -0
- package/dist/tools/unit-cost.js.map +1 -0
- package/dist/tools/verify-fix.d.ts.map +1 -1
- package/dist/tools/verify-fix.js +11 -3
- package/dist/tools/verify-fix.js.map +1 -1
- package/dist/tools/weakref-census.d.ts +15 -0
- package/dist/tools/weakref-census.d.ts.map +1 -0
- package/dist/tools/weakref-census.js +147 -0
- package/dist/tools/weakref-census.js.map +1 -0
- package/dist/tools/what-if.d.ts +12 -0
- package/dist/tools/what-if.d.ts.map +1 -0
- package/dist/tools/what-if.js +285 -0
- package/dist/tools/what-if.js.map +1 -0
- package/dist/utils.d.ts +92 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +172 -5
- package/dist/utils.js.map +1 -1
- 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
|
-
|
|
38
|
-
|
|
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(
|
|
41
|
-
const parsed = JSON.parse(fs.readFileSync(
|
|
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(
|
|
59
|
-
fs.renameSync(
|
|
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
|
-
|
|
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(
|
|
70
|
-
fs.writeFileSync(
|
|
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
|
|
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
|
-
|
|
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
|
|
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 (
|
|
143
|
-
return toolResult(
|
|
144
|
-
'
|
|
145
|
-
'
|
|
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
|
-
|
|
205
|
-
'Confirm it, then `action: "record"` so the next
|
|
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":"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"}
|
|
@@ -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;
|
|
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"}
|
package/dist/tools/get-value.js
CHANGED
|
@@ -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
|
-
|
|
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);
|