memorydetective 1.13.0 → 1.14.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 (44) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +6 -2
  3. package/USAGE.md +29 -0
  4. package/dist/index.js +9 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/parsers/schemaDiscovery.d.ts +88 -0
  7. package/dist/parsers/schemaDiscovery.js +144 -0
  8. package/dist/parsers/schemaDiscovery.js.map +1 -0
  9. package/dist/parsers/xctraceXml.d.ts +5 -0
  10. package/dist/parsers/xctraceXml.js +3 -0
  11. package/dist/parsers/xctraceXml.js.map +1 -1
  12. package/dist/tools/analyzeAllocations.d.ts +5 -1
  13. package/dist/tools/analyzeAllocations.js +17 -1
  14. package/dist/tools/analyzeAllocations.js.map +1 -1
  15. package/dist/tools/analyzeAnimationHitches.d.ts +5 -1
  16. package/dist/tools/analyzeAnimationHitches.js +17 -1
  17. package/dist/tools/analyzeAnimationHitches.js.map +1 -1
  18. package/dist/tools/analyzeAppLaunch.d.ts +3 -0
  19. package/dist/tools/analyzeAppLaunch.js +17 -1
  20. package/dist/tools/analyzeAppLaunch.js.map +1 -1
  21. package/dist/tools/analyzeHangs.d.ts +63 -3
  22. package/dist/tools/analyzeHangs.js +143 -19
  23. package/dist/tools/analyzeHangs.js.map +1 -1
  24. package/dist/tools/analyzeNetworkActivity.d.ts +99 -0
  25. package/dist/tools/analyzeNetworkActivity.js +312 -0
  26. package/dist/tools/analyzeNetworkActivity.js.map +1 -0
  27. package/dist/tools/analyzeTimeProfile.d.ts +10 -1
  28. package/dist/tools/analyzeTimeProfile.js +63 -8
  29. package/dist/tools/analyzeTimeProfile.js.map +1 -1
  30. package/dist/tools/countAlive.d.ts +35 -1
  31. package/dist/tools/countAlive.js +124 -29
  32. package/dist/tools/countAlive.js.map +1 -1
  33. package/dist/tools/inspectTrace.js +112 -18
  34. package/dist/tools/inspectTrace.js.map +1 -1
  35. package/dist/tools/recordTimeProfile.d.ts +83 -0
  36. package/dist/tools/recordTimeProfile.js +135 -0
  37. package/dist/tools/recordTimeProfile.js.map +1 -1
  38. package/dist/tools/replayScenario.d.ts +4 -4
  39. package/dist/tools/summarizeTrace.d.ts +2 -2
  40. package/dist/tools/verifyFix.d.ts +27 -0
  41. package/dist/tools/verifyFix.js +78 -4
  42. package/dist/tools/verifyFix.js.map +1 -1
  43. package/dist/types.d.ts +28 -0
  44. package/package.json +2 -2
@@ -5,16 +5,19 @@ export declare const countAliveSchema: z.ZodObject<{
5
5
  className: z.ZodOptional<z.ZodString>;
6
6
  topN: z.ZodDefault<z.ZodNumber>;
7
7
  includeReferenceTree: z.ZodDefault<z.ZodBoolean>;
8
+ sortBy: z.ZodDefault<z.ZodEnum<["count", "totalBytes"]>>;
8
9
  }, "strip", z.ZodTypeAny, {
9
10
  path: string;
10
11
  topN: number;
11
12
  includeReferenceTree: boolean;
13
+ sortBy: "count" | "totalBytes";
12
14
  className?: string | undefined;
13
15
  }, {
14
16
  path: string;
15
17
  className?: string | undefined;
16
18
  topN?: number | undefined;
17
19
  includeReferenceTree?: boolean | undefined;
20
+ sortBy?: "count" | "totalBytes" | undefined;
18
21
  }>;
19
22
  export type CountAliveInput = z.infer<typeof countAliveSchema>;
20
23
  export interface CountAliveEntry {
@@ -24,6 +27,22 @@ export interface CountAliveEntry {
24
27
  byCycle?: number;
25
28
  /** When `includeReferenceTree: true`, the reference-tree contribution. Often the only non-zero side on `leakCount: 0` memgraphs. */
26
29
  byReferenceTree?: number;
30
+ /**
31
+ * v1.14+. Per-instance size in bytes derived from the memgraph. For
32
+ * fixed-size ObjC classes every instance has the same size; for
33
+ * variable-size classes (NSData with payload, etc.) this is an average
34
+ * (totalBytes / instanceCount, rounded). Absent when neither the
35
+ * cycle-side `[N]` annotation nor the reference-tree parens-size
36
+ * carried a number (rare).
37
+ */
38
+ instanceSizeBytes?: number;
39
+ /**
40
+ * v1.14+. Total bytes attributed to this class: sum of per-instance
41
+ * sizes from the cycle forest plus the reference-tree totals. FLEX
42
+ * surfaces this as the "Size" sort column in its Live Objects view.
43
+ * Useful for "where is my memory going?" investigations.
44
+ */
45
+ totalBytes?: number;
27
46
  }
28
47
  export interface CountAliveResult {
29
48
  ok: boolean;
@@ -41,6 +60,21 @@ export interface CountAliveResult {
41
60
  */
42
61
  actionableCounts?: CountAliveEntry[];
43
62
  }
44
- /** Pure: count node occurrences by exact className across the cycle forest. */
63
+ /** Pure: count node occurrences by exact className across the cycle forest.
64
+ * Backwards-compatible API; for v1.14 byte aggregation use
65
+ * {@link countByClassWithBytes}. */
45
66
  export declare function countByClass(report: LeaksReport): Map<string, number>;
67
+ /**
68
+ * Pure: aggregate occurrences AND bytes by exact className across the
69
+ * cycle forest. Each node's `instanceSize` is summed into `totalBytes`;
70
+ * the first non-zero `instanceSize` seen is recorded as the canonical
71
+ * `instanceSizeBytes` (ObjC classes are typically fixed-size, so the
72
+ * first value is representative). Nodes without a size annotation
73
+ * contribute to count but not bytes. v1.14.
74
+ */
75
+ export declare function countByClassWithBytes(report: LeaksReport): Map<string, {
76
+ count: number;
77
+ totalBytes: number;
78
+ instanceSizeBytes?: number;
79
+ }>;
46
80
  export declare function countAlive(input: CountAliveInput): Promise<CountAliveResult>;
@@ -19,8 +19,14 @@ export const countAliveSchema = z.object({
19
19
  .boolean()
20
20
  .default(false)
21
21
  .describe("v1.12+. When true, also parse `leaks --referenceTree --groupByType --noContent` output and surface heap-wide instance counts alongside the cycle-side counts. Required to find classes on memgraphs where `leakCount: 0` and the abandoned-memory shape is what's interesting (e.g. orphaned KVO observers reachable from the global registry). Adds a second `leaks` invocation, run in parallel. Default false preserves v1.11 behavior."),
22
+ sortBy: z
23
+ .enum(["count", "totalBytes"])
24
+ .default("count")
25
+ .describe("v1.14+. Ranks the topN by either instance count (default, preserves v1.13 behavior) or total bytes (FLEX's 'Size' sort). totalBytes is `count * instanceSizeBytes` and is the right rank for 'where is my memory going?' investigations vs 'how many instances are alive?'. Per-class instanceSizeBytes + totalBytes are returned regardless of sort key."),
22
26
  });
23
- /** Pure: count node occurrences by exact className across the cycle forest. */
27
+ /** Pure: count node occurrences by exact className across the cycle forest.
28
+ * Backwards-compatible API; for v1.14 byte aggregation use
29
+ * {@link countByClassWithBytes}. */
24
30
  export function countByClass(report) {
25
31
  const counts = new Map();
26
32
  for (const { node } of walkCycles(report.cycles)) {
@@ -30,6 +36,30 @@ export function countByClass(report) {
30
36
  }
31
37
  return counts;
32
38
  }
39
+ /**
40
+ * Pure: aggregate occurrences AND bytes by exact className across the
41
+ * cycle forest. Each node's `instanceSize` is summed into `totalBytes`;
42
+ * the first non-zero `instanceSize` seen is recorded as the canonical
43
+ * `instanceSizeBytes` (ObjC classes are typically fixed-size, so the
44
+ * first value is representative). Nodes without a size annotation
45
+ * contribute to count but not bytes. v1.14.
46
+ */
47
+ export function countByClassWithBytes(report) {
48
+ const acc = new Map();
49
+ for (const { node } of walkCycles(report.cycles)) {
50
+ if (!node.className)
51
+ continue;
52
+ const cur = acc.get(node.className) ?? { count: 0, totalBytes: 0 };
53
+ cur.count += 1;
54
+ if (node.instanceSize != null) {
55
+ cur.totalBytes += node.instanceSize;
56
+ if (cur.instanceSizeBytes == null)
57
+ cur.instanceSizeBytes = node.instanceSize;
58
+ }
59
+ acc.set(node.className, cur);
60
+ }
61
+ return acc;
62
+ }
33
63
  /**
34
64
  * Spawn `leaks --referenceTree --groupByType --noContent` and parse the
35
65
  * stdout. Non-fatal on failure: returns empty array so the cycle-side
@@ -41,37 +71,64 @@ async function captureReferenceTreeCounts(path) {
41
71
  if (result.code !== 0 && result.code !== 1)
42
72
  return new Map();
43
73
  const entries = parseReferenceTreeText(result.stdout, 5000);
44
- return new Map(entries.map((e) => [e.className, e.instanceCount]));
74
+ return new Map(entries.map((e) => [
75
+ e.className,
76
+ { count: e.instanceCount, totalBytes: e.totalBytes },
77
+ ]));
45
78
  }
46
79
  export async function countAlive(input) {
47
80
  const wantReferenceTree = input.includeReferenceTree ?? false;
81
+ const sortBy = input.sortBy ?? "count";
48
82
  const [{ report, resolvedPath }, refTreeCounts] = await Promise.all([
49
83
  runLeaksAndParse(input.path),
50
84
  wantReferenceTree
51
85
  ? captureReferenceTreeCounts(input.path)
52
86
  : Promise.resolve(new Map()),
53
87
  ]);
54
- const cycleCounts = countByClass(report);
55
- const totalNodes = Array.from(cycleCounts.values()).reduce((a, b) => a + b, 0);
88
+ const cycleByClass = countByClassWithBytes(report);
89
+ const totalNodes = Array.from(cycleByClass.values()).reduce((a, b) => a + b.count, 0);
56
90
  if (input.className) {
57
91
  let cycleMatched = 0;
58
- for (const [name, n] of cycleCounts.entries()) {
59
- if (name.includes(input.className))
60
- cycleMatched += n;
92
+ let cycleBytesMatched = 0;
93
+ let cycleInstanceSize;
94
+ for (const [name, info] of cycleByClass.entries()) {
95
+ if (!name.includes(input.className))
96
+ continue;
97
+ cycleMatched += info.count;
98
+ cycleBytesMatched += info.totalBytes;
99
+ if (cycleInstanceSize == null && info.instanceSizeBytes != null) {
100
+ cycleInstanceSize = info.instanceSizeBytes;
101
+ }
61
102
  }
62
103
  let refTreeMatched = 0;
63
- for (const [name, n] of refTreeCounts.entries()) {
64
- if (name.includes(input.className))
65
- refTreeMatched += n;
104
+ let refTreeBytesMatched = 0;
105
+ for (const [name, info] of refTreeCounts.entries()) {
106
+ if (!name.includes(input.className))
107
+ continue;
108
+ refTreeMatched += info.count;
109
+ refTreeBytesMatched += info.totalBytes;
66
110
  }
111
+ const totalCount = cycleMatched + refTreeMatched;
112
+ const totalBytes = cycleBytesMatched + refTreeBytesMatched;
113
+ const instanceSizeBytes = cycleInstanceSize ??
114
+ (totalCount > 0 && totalBytes > 0
115
+ ? Math.round(totalBytes / totalCount)
116
+ : undefined);
67
117
  const entry = wantReferenceTree
68
118
  ? {
69
119
  className: input.className,
70
- instanceCount: cycleMatched + refTreeMatched,
120
+ instanceCount: totalCount,
71
121
  byCycle: cycleMatched,
72
122
  byReferenceTree: refTreeMatched,
123
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
124
+ ...(totalBytes > 0 ? { totalBytes } : {}),
73
125
  }
74
- : { className: input.className, instanceCount: cycleMatched };
126
+ : {
127
+ className: input.className,
128
+ instanceCount: cycleMatched,
129
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
130
+ ...(cycleBytesMatched > 0 ? { totalBytes: cycleBytesMatched } : {}),
131
+ };
75
132
  return {
76
133
  ok: true,
77
134
  path: resolvedPath,
@@ -80,31 +137,69 @@ export async function countAlive(input) {
80
137
  };
81
138
  }
82
139
  // topN path. Merge cycle + reference-tree counts when the flag is on,
83
- // ordered by instanceCount desc.
140
+ // ordered by sortBy (default 'count', or 'totalBytes' for FLEX-style
141
+ // memory-budget rank).
84
142
  const merged = new Map();
85
- for (const [name, n] of cycleCounts.entries()) {
86
- merged.set(name, { byCycle: n, byReferenceTree: 0 });
143
+ for (const [name, info] of cycleByClass.entries()) {
144
+ merged.set(name, {
145
+ byCycle: info.count,
146
+ byReferenceTree: 0,
147
+ cycleBytes: info.totalBytes,
148
+ refTreeBytes: 0,
149
+ ...(info.instanceSizeBytes != null
150
+ ? { instanceSizeBytes: info.instanceSizeBytes }
151
+ : {}),
152
+ });
87
153
  }
88
154
  if (wantReferenceTree) {
89
- for (const [name, n] of refTreeCounts.entries()) {
155
+ for (const [name, info] of refTreeCounts.entries()) {
90
156
  const existing = merged.get(name);
91
- if (existing)
92
- existing.byReferenceTree = n;
93
- else
94
- merged.set(name, { byCycle: 0, byReferenceTree: n });
157
+ if (existing) {
158
+ existing.byReferenceTree = info.count;
159
+ existing.refTreeBytes = info.totalBytes;
160
+ }
161
+ else {
162
+ merged.set(name, {
163
+ byCycle: 0,
164
+ byReferenceTree: info.count,
165
+ cycleBytes: 0,
166
+ refTreeBytes: info.totalBytes,
167
+ });
168
+ }
95
169
  }
96
170
  }
97
171
  const topN = input.topN ?? 20;
98
- const allEntries = Array.from(merged.entries())
99
- .map(([name, v]) => wantReferenceTree
100
- ? {
101
- className: name,
102
- instanceCount: v.byCycle + v.byReferenceTree,
103
- byCycle: v.byCycle,
104
- byReferenceTree: v.byReferenceTree,
172
+ const allEntries = Array.from(merged.entries()).map(([name, v]) => {
173
+ const totalCount = v.byCycle + v.byReferenceTree;
174
+ const totalBytes = v.cycleBytes + v.refTreeBytes;
175
+ const instanceSizeBytes = v.instanceSizeBytes ??
176
+ (totalCount > 0 && totalBytes > 0
177
+ ? Math.round(totalBytes / totalCount)
178
+ : undefined);
179
+ return wantReferenceTree
180
+ ? {
181
+ className: name,
182
+ instanceCount: totalCount,
183
+ byCycle: v.byCycle,
184
+ byReferenceTree: v.byReferenceTree,
185
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
186
+ ...(totalBytes > 0 ? { totalBytes } : {}),
187
+ }
188
+ : {
189
+ className: name,
190
+ instanceCount: v.byCycle,
191
+ ...(instanceSizeBytes != null ? { instanceSizeBytes } : {}),
192
+ ...(v.cycleBytes > 0 ? { totalBytes: v.cycleBytes } : {}),
193
+ };
194
+ });
195
+ allEntries.sort((a, b) => {
196
+ if (sortBy === "totalBytes") {
197
+ const ad = (b.totalBytes ?? 0) - (a.totalBytes ?? 0);
198
+ if (ad !== 0)
199
+ return ad;
105
200
  }
106
- : { className: name, instanceCount: v.byCycle })
107
- .sort((a, b) => b.instanceCount - a.instanceCount);
201
+ return b.instanceCount - a.instanceCount;
202
+ });
108
203
  const top = allEntries.slice(0, topN);
109
204
  const result = {
110
205
  ok: true,
@@ -1 +1 @@
1
- {"version":3,"file":"countAlive.js","sourceRoot":"","sources":["../../src/tools/countAlive.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"countAlive.js","sourceRoot":"","sources":["../../src/tools/countAlive.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,10 @@ const SCHEMA_TO_ANALYZER = {
62
62
  tool: "analyzeAppLaunch",
63
63
  description: "Returns cold/warm launch type plus per-phase breakdown (process-creation, dyld-init, ObjC-init, AppDelegate, first-frame).",
64
64
  },
65
+ "network-connections": {
66
+ tool: "analyzeNetworkActivity",
67
+ description: "Per-request URL / host / method / status / response time / bytes. Top-N by duration and by bytes plus per-host aggregates.",
68
+ },
65
69
  };
66
70
  /** Pure: parse the trace-toc XML payload into an inspection result. */
67
71
  export function parseTraceToc(xml, tracePath) {
@@ -72,16 +76,22 @@ export function parseTraceToc(xml, tracePath) {
72
76
  // Surfacing only schema metadata + row counts is faster and avoids
73
77
  // pulling row payloads into memory for traces that have hundreds of
74
78
  // thousands of rows.
75
- // Match each <table schema="X"> block.
76
- const tableRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*>([\s\S]*?)<\/table>/g;
79
+ //
80
+ // Apple's `xctrace export --toc` emits self-closing `<table schema="X"/>`
81
+ // elements (the TOC carries column definitions only, no rows). Older
82
+ // synthetic fixtures and some xctrace versions use the open-close form
83
+ // `<table schema="X">...<row/>...</table>`. We match BOTH and fall back
84
+ // to row-counting from the body when present.
85
+ // Open-close form first: `<table schema="X">body</table>`.
86
+ const openCloseRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*>([\s\S]*?)<\/table>/g;
87
+ const seenRanges = [];
77
88
  let match;
78
- while ((match = tableRegex.exec(xml)) !== null) {
89
+ while ((match = openCloseRegex.exec(xml)) !== null) {
79
90
  const name = match[1];
80
91
  const body = match[2];
81
- // Row count = number of <row> tags inside this table.
92
+ seenRanges.push([match.index, match.index + match[0].length]);
82
93
  const rowMatches = body.match(/<row\b/g);
83
94
  const rowCount = rowMatches ? rowMatches.length : 0;
84
- // Description: schema may carry an `engineering-type` description.
85
95
  const descMatch = /<engineering-description>([^<]+)<\/engineering-description>/.exec(body);
86
96
  const description = descMatch?.[1]?.trim();
87
97
  schemas.push({
@@ -90,15 +100,36 @@ export function parseTraceToc(xml, tracePath) {
90
100
  ...(description ? { description } : {}),
91
101
  });
92
102
  }
103
+ // Self-closing form: `<table schema="X" .../>`. Skip ranges already
104
+ // matched by openCloseRegex so we don't double-count when a body contains
105
+ // nested self-closing tables (unlikely but defensive).
106
+ const selfCloseRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*\/>/g;
107
+ while ((match = selfCloseRegex.exec(xml)) !== null) {
108
+ const start = match.index;
109
+ if (seenRanges.some(([s, e]) => start >= s && start < e))
110
+ continue;
111
+ const name = match[1];
112
+ schemas.push({
113
+ name,
114
+ rowCount: 0, // TOC self-closing tables carry no rows; rowCount must be filled by the async row-counting step in inspectTrace().
115
+ });
116
+ }
93
117
  schemas.sort((a, b) => b.rowCount - a.rowCount);
94
118
  const rowCounts = {};
95
119
  for (const s of schemas)
96
120
  rowCounts[s.name] = s.rowCount;
97
121
  // Run-level metadata extracted from the TOC's <run> attributes / children.
98
- const deviceMatch = /<device-model>([^<]+)<\/device-model>/.exec(xml);
99
- const osMatch = /<os-version>([^<]+)<\/os-version>/.exec(xml);
122
+ // Apple's --toc output exposes device + OS as ATTRIBUTES on <device .../>
123
+ // and uses <start-date> instead of <recorded-when>. We try the Apple
124
+ // attribute form first, fall back to legacy text-element form for
125
+ // synthetic fixtures.
126
+ const deviceAttrMatch = /<device\b[^>]*\bmodel="([^"]+)"/.exec(xml);
127
+ const deviceMatch = deviceAttrMatch ?? /<device-model>([^<]+)<\/device-model>/.exec(xml);
128
+ const osAttrMatch = /<device\b[^>]*\bos-version="([^"]+)"/.exec(xml);
129
+ const osMatch = osAttrMatch ?? /<os-version>([^<]+)<\/os-version>/.exec(xml);
100
130
  const templateMatch = /<template-name>([^<]+)<\/template-name>/.exec(xml);
101
- const recordedMatch = /<recorded-when>([^<]+)<\/recorded-when>/.exec(xml);
131
+ const recordedAttrMatch = /<start-date>([^<]+)<\/start-date>/.exec(xml);
132
+ const recordedMatch = recordedAttrMatch ?? /<recorded-when>([^<]+)<\/recorded-when>/.exec(xml);
102
133
  const suggestedNextCalls = [];
103
134
  for (const s of schemas) {
104
135
  if (s.rowCount === 0)
@@ -142,6 +173,36 @@ function buildDiagnosis(schemas, templateName) {
142
173
  }
143
174
  return parts.join(" ");
144
175
  }
176
+ /**
177
+ * Count `<row>` elements for a single schema by running a targeted xpath
178
+ * query. Used by `inspectTrace` to fill in row counts that the bare
179
+ * `--toc` output omits (Apple's TOC emits self-closing `<table/>` elements
180
+ * with column metadata only, no rows).
181
+ *
182
+ * Bounded by a 60s xctrace timeout each. On any failure we treat as zero
183
+ * rows rather than throwing: an empty result is the same semantic outcome
184
+ * as a missing schema, and downstream `summarizeTrace` already handles
185
+ * `rowCount === 0` as "schema-absent".
186
+ */
187
+ async function countSchemaRows(tracePath, schemaName) {
188
+ try {
189
+ const result = await runCommand("xcrun", [
190
+ "xctrace",
191
+ "export",
192
+ "--input",
193
+ tracePath,
194
+ "--xpath",
195
+ `/trace-toc/run/data/table[@schema="${schemaName}"]`,
196
+ ], { timeoutMs: 60_000 });
197
+ if (result.code !== 0)
198
+ return 0;
199
+ const rowMatches = result.stdout.match(/<row\b/g);
200
+ return rowMatches ? rowMatches.length : 0;
201
+ }
202
+ catch {
203
+ return 0;
204
+ }
205
+ }
145
206
  export async function inspectTrace(input) {
146
207
  const tracePath = resolvePath(input.tracePath);
147
208
  if (!existsSync(tracePath)) {
@@ -155,22 +216,55 @@ export async function inspectTrace(input) {
155
216
  // The bundle is a directory on macOS; stat reports the directory inode
156
217
  // size, which is fine for orientation. Failures are non-fatal.
157
218
  }
158
- const result = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--xpath", "/trace-toc/run"], { timeoutMs: 60_000 });
219
+ // Apple's `xctrace export --toc` is the canonical schema-discovery surface.
220
+ // The previously-used `--xpath '/trace-toc/run'` returns "no content to
221
+ // export" against real Apple-produced .trace bundles (validated 2026-05-15
222
+ // against wishlist-tti-device.trace). The --toc flag returns the full
223
+ // table-of-contents XML including all `<table schema="..."/>` elements.
224
+ const result = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--toc"], { timeoutMs: 60_000 });
159
225
  if (result.code !== 0) {
160
- // Fallback: when the targeted xpath fails (older xctrace versions, or
161
- // a trace with no /run node), try the broader /trace-toc xpath and
162
- // parse whatever schemas surface.
163
- const fallback = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--xpath", "/trace-toc"], { timeoutMs: 60_000 });
164
- if (fallback.code !== 0) {
165
- throw new Error(`xctrace export TOC failed (code ${result.code}): ${result.stderr || result.stdout || "<no output>"}`);
166
- }
167
- const parsed = parseTraceToc(fallback.stdout, tracePath);
168
- return { ok: true, ...parsed, ...(fileSize != null ? { fileSize } : {}) };
226
+ throw new Error(`xctrace export --toc failed (code ${result.code}): ${result.stderr || result.stdout || "<no output>"}`);
169
227
  }
170
228
  const parsed = parseTraceToc(result.stdout, tracePath);
229
+ // The TOC carries schema NAMES + column metadata but no rows. Fill in
230
+ // row counts for the schemas an analyzer can consume (the ones in
231
+ // SCHEMA_TO_ANALYZER) so `summarizeTrace` can decide which analyzers to
232
+ // run. Other schemas (tick, kdebug, life-cycle-period, etc.) are left at
233
+ // rowCount=0; nothing downstream consumes them.
234
+ const knownSchemas = Object.keys(SCHEMA_TO_ANALYZER);
235
+ const schemasInTrace = new Set(parsed.schemas.map((s) => s.name));
236
+ const schemasToCount = knownSchemas.filter((name) => schemasInTrace.has(name));
237
+ const counts = await Promise.all(schemasToCount.map(async (name) => [name, await countSchemaRows(tracePath, name)]));
238
+ const rowCounts = { ...parsed.rowCounts };
239
+ for (const [name, count] of counts)
240
+ rowCounts[name] = count;
241
+ const updatedSchemas = parsed.schemas.map((s) => rowCounts[s.name] != null && rowCounts[s.name] !== s.rowCount
242
+ ? { ...s, rowCount: rowCounts[s.name] }
243
+ : s);
244
+ updatedSchemas.sort((a, b) => b.rowCount - a.rowCount);
245
+ // Recompute suggestedNextCalls now that row counts are accurate.
246
+ const suggestedNextCalls = [];
247
+ for (const s of updatedSchemas) {
248
+ if (s.rowCount === 0)
249
+ continue;
250
+ const mapping = SCHEMA_TO_ANALYZER[s.name];
251
+ if (!mapping)
252
+ continue;
253
+ suggestedNextCalls.push({
254
+ tool: mapping.tool,
255
+ args: { tracePath },
256
+ why: `${s.rowCount.toLocaleString()} rows in the ${s.name} schema. ${mapping.description}`,
257
+ });
258
+ }
259
+ // Recompute diagnosis with accurate row counts.
260
+ const diagnosis = buildDiagnosis(updatedSchemas, parsed.templateName);
171
261
  return {
172
262
  ok: true,
173
263
  ...parsed,
264
+ schemas: updatedSchemas,
265
+ rowCounts,
266
+ suggestedNextCalls,
267
+ diagnosis,
174
268
  ...(fileSize != null ? { fileSize } : {}),
175
269
  };
176
270
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inspectTrace.js","sourceRoot":"","sources":["../../src/tools/inspectTrace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inspectTrace.js","sourceRoot":"","sources":["../../src/tools/inspectTrace.ts"],"names":[],"mappings":"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"}
@@ -87,7 +87,90 @@ export interface RecordTimeProfileResult {
87
87
  * and the practical mitigations.
88
88
  */
89
89
  workaroundNotice?: RecordingTimeoutWorkaroundNotice;
90
+ /**
91
+ * v1.14+. `true` when, after a timed-out recording, the wrapper invoked
92
+ * `open -a Instruments <tracePath>` so the user can inspect the partial
93
+ * trace in the GUI (Instruments.app on macOS 26.x can still open and
94
+ * symbolicate traces the CLI export path rejects). Opt-in via
95
+ * `MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS=1`. `false` when the env flag is
96
+ * unset (default) or the trace bundle is missing from disk. Absent when
97
+ * the recording did not time out.
98
+ */
99
+ openedInInstrumentsApp?: boolean;
100
+ }
101
+ /**
102
+ * v1.14 item H. Pre-flight probe for the xctrace `--time-limit` ignore
103
+ * regression on macOS 26.x simulators. Runs a 2-second test recording
104
+ * against the same target the user requested. If the probe completes
105
+ * cleanly inside its wrapper window, the user's full recording is
106
+ * expected to behave; if the probe times out, we bail before spending
107
+ * the user's full `durationSec` + 30s grace window on a wedge.
108
+ *
109
+ * Returns `{ healthy: true }` when the probe exited cleanly. Returns
110
+ * `{ healthy: false, reason }` when the probe timed out OR when xctrace
111
+ * exited non-zero (the wedge does not always produce timedOut=true;
112
+ * sometimes xctrace exits early with a misleading error code when the
113
+ * sim is in a bad state). The recordTimeProfile flow treats either as
114
+ * "skip the full recording, return workaroundNotice now".
115
+ *
116
+ * Pre-flight is gated to ATTACH mode only. The `--launch` path would
117
+ * start the user's app a second time (probe launch + full-recording
118
+ * launch), losing first-launch state. For `--launch` callers we skip
119
+ * the probe and fall back to the existing 70s timeout wrapper.
120
+ *
121
+ * Exported so the gating logic can be unit-tested without spawning
122
+ * xctrace.
123
+ */
124
+ export interface PreflightResult {
125
+ healthy: boolean;
126
+ reason?: string;
127
+ durationMs: number;
90
128
  }
129
+ /**
130
+ * Returns true when a pre-flight probe should run before the user's
131
+ * actual recording. v1.14 item H.
132
+ *
133
+ * - `MEMORYDETECTIVE_PREFLIGHT_XCTRACE=1` forces preflight on.
134
+ * - `MEMORYDETECTIVE_PREFLIGHT_XCTRACE=0` forces it off.
135
+ * - Default: auto-enabled when host is macOS 26.x AND target is a
136
+ * simulator AND attach mode (`--attach`, not `--launch`). The set of
137
+ * configurations where the regression is known to fire.
138
+ *
139
+ * The `osPlatform` and `osRelease` params are threaded through to
140
+ * `getPlatformAdvisory` so tests can simulate non-macOS-26 hosts even
141
+ * when running on a real macOS 26.x machine.
142
+ */
143
+ export declare function shouldPreflightXctrace(input: RecordTimeProfileInput, env?: Readonly<Record<string, string | undefined>>, osPlatform?: () => NodeJS.Platform, osRelease?: () => string): boolean;
144
+ /**
145
+ * Runs the 2-second probe. Reuses runCommand's timeout wrapper with the
146
+ * same SIGINT-first / SIGKILL-fallback shape that the full recording
147
+ * uses, so the probe's salvage behavior matches the real path.
148
+ *
149
+ * The output bundle is placed at `<output>.preflight` to keep it
150
+ * recognizable in cleanup tools and not collide with the user's actual
151
+ * output path.
152
+ */
153
+ export declare function preflightXctraceRecord(input: RecordTimeProfileInput, resolvedOutput: string): Promise<PreflightResult>;
154
+ /**
155
+ * v1.14 item J. When a `recordTimeProfile` call times out, optionally
156
+ * launch the partial `.trace` in Instruments.app so the user has a GUI
157
+ * escape hatch. Returns `true` when `open -a Instruments <tracePath>`
158
+ * was spawned, `false` otherwise.
159
+ *
160
+ * Gated on `MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS=1` to avoid spamming
161
+ * the user's GUI on unattended runs and CI. Also requires the trace
162
+ * bundle to exist on disk (xctrace's SIGINT path may have failed to
163
+ * write anything).
164
+ *
165
+ * The `open` invocation is fire-and-forget: `detached: true` + `unref()`
166
+ * so the recording tool returns immediately. Failures to launch
167
+ * Instruments.app are swallowed; the user is no worse off than without
168
+ * the flag enabled.
169
+ *
170
+ * Exported so the env-gating logic can be tested without spawning
171
+ * Instruments in test runs.
172
+ */
173
+ export declare function maybeOpenInInstruments(tracePath: string): boolean;
91
174
  /** Pure: build the xctrace argv for the given input. Exposed for testing. */
92
175
  export declare function buildXctraceArgs(input: RecordTimeProfileInput): string[];
93
176
  export declare function recordTimeProfile(input: RecordTimeProfileInput): Promise<RecordTimeProfileResult>;