memorydetective 1.9.0 → 1.11.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.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * `inspectTrace`: orientation tool for `.trace` bundles. Lists which
3
+ * schemas are present, how many rows each carries, the time range, the
4
+ * device model, the template name, and a pre-baked `suggestedNextCalls`
5
+ * pointing at the matching analyzer for each populated schema.
6
+ *
7
+ * The use case is "I have a .trace, what's worth looking at?". Without
8
+ * this tool the caller has to either pick an `analyze*` blindly or
9
+ * read the full xctrace export which is wasteful. The MCP-native
10
+ * agent loop benefits the most: discovery costs 1 call instead of 5.
11
+ *
12
+ * Implementation notes:
13
+ *
14
+ * - Single `xctrace export --xpath '/trace-toc/run'` invocation. Returns
15
+ * the run metadata + all table schemas in one shot. We parse just enough
16
+ * to enumerate schemas + count rows; we deliberately do NOT parse row
17
+ * contents (the downstream `analyze*` tools do that).
18
+ *
19
+ * - Time range: derived from the schema-level `start-time` / `end-time`
20
+ * attributes when present; falls back to the run's `<recorded-when>`
21
+ * timestamp string when not parseable.
22
+ *
23
+ * - The 5 known schemas (potential-hangs, animation-hitches, time-profile,
24
+ * allocations, app-launch) map 1:1 to the existing analyzers. Any
25
+ * schema NOT in that map is still surfaced in the `schemas[]` list (so
26
+ * the user sees it) but does not contribute a `suggestedNextCalls`
27
+ * entry — there's no analyzer to chain into.
28
+ */
29
+ import { z } from "zod";
30
+ import type { NextCallSuggestion } from "../types.js";
31
+ export declare const inspectTraceSchema: z.ZodObject<{
32
+ tracePath: z.ZodString;
33
+ }, "strip", z.ZodTypeAny, {
34
+ tracePath: string;
35
+ }, {
36
+ tracePath: string;
37
+ }>;
38
+ export type InspectTraceInput = z.infer<typeof inspectTraceSchema>;
39
+ export interface TraceSchemaSummary {
40
+ /** Schema name (e.g. "potential-hangs", "time-profile"). */
41
+ name: string;
42
+ /** Number of rows in this schema's table. 0 means the schema is present in the trace but carries no data. */
43
+ rowCount: number;
44
+ /** Engineering description when the schema declares one; absent otherwise. */
45
+ description?: string;
46
+ }
47
+ export interface InspectTraceResult {
48
+ ok: boolean;
49
+ tracePath: string;
50
+ /** All schemas present in the trace TOC, ranked by rowCount desc. */
51
+ schemas: TraceSchemaSummary[];
52
+ /** Convenience: schemaName -> rowCount, same data as `schemas[]` in object form. */
53
+ rowCounts: Record<string, number>;
54
+ /** Trace file size in bytes (the .trace bundle is a directory; reports the directory entry size, not recursive). */
55
+ fileSize?: number;
56
+ /** Device model name when the trace's run metadata exposes one. */
57
+ deviceModel?: string;
58
+ /** OS version when present. */
59
+ osVersion?: string;
60
+ /** Template name (e.g. "Time Profiler", "Allocations"). */
61
+ templateName?: string;
62
+ /** Recording timestamp string (raw, unparsed). */
63
+ recordedWhen?: string;
64
+ /** Plain-English orientation diagnosis. */
65
+ diagnosis: string;
66
+ /** Pipeline hints based on which analyzers have data to chain into. */
67
+ suggestedNextCalls: NextCallSuggestion[];
68
+ }
69
+ /** Pure: parse the trace-toc XML payload into an inspection result. */
70
+ export declare function parseTraceToc(xml: string, tracePath: string): Omit<InspectTraceResult, "ok" | "fileSize">;
71
+ export declare function inspectTrace(input: InspectTraceInput): Promise<InspectTraceResult>;
72
+ export declare function _basenameForTests(p: string): string;
@@ -0,0 +1,181 @@
1
+ /**
2
+ * `inspectTrace`: orientation tool for `.trace` bundles. Lists which
3
+ * schemas are present, how many rows each carries, the time range, the
4
+ * device model, the template name, and a pre-baked `suggestedNextCalls`
5
+ * pointing at the matching analyzer for each populated schema.
6
+ *
7
+ * The use case is "I have a .trace, what's worth looking at?". Without
8
+ * this tool the caller has to either pick an `analyze*` blindly or
9
+ * read the full xctrace export which is wasteful. The MCP-native
10
+ * agent loop benefits the most: discovery costs 1 call instead of 5.
11
+ *
12
+ * Implementation notes:
13
+ *
14
+ * - Single `xctrace export --xpath '/trace-toc/run'` invocation. Returns
15
+ * the run metadata + all table schemas in one shot. We parse just enough
16
+ * to enumerate schemas + count rows; we deliberately do NOT parse row
17
+ * contents (the downstream `analyze*` tools do that).
18
+ *
19
+ * - Time range: derived from the schema-level `start-time` / `end-time`
20
+ * attributes when present; falls back to the run's `<recorded-when>`
21
+ * timestamp string when not parseable.
22
+ *
23
+ * - The 5 known schemas (potential-hangs, animation-hitches, time-profile,
24
+ * allocations, app-launch) map 1:1 to the existing analyzers. Any
25
+ * schema NOT in that map is still surfaced in the `schemas[]` list (so
26
+ * the user sees it) but does not contribute a `suggestedNextCalls`
27
+ * entry — there's no analyzer to chain into.
28
+ */
29
+ import { z } from "zod";
30
+ import { existsSync } from "node:fs";
31
+ import { resolve as resolvePath, basename } from "node:path";
32
+ import { statSync } from "node:fs";
33
+ import { runCommand } from "../runtime/exec.js";
34
+ export const inspectTraceSchema = z.object({
35
+ tracePath: z
36
+ .string()
37
+ .min(1)
38
+ .describe("Absolute path to a `.trace` bundle (output of `xcrun xctrace record` or Instruments)."),
39
+ });
40
+ /**
41
+ * Map from xctrace schema name to the analyzer that consumes it. Drives
42
+ * `suggestedNextCalls[]` so the agent doesn't have to know the mapping.
43
+ */
44
+ const SCHEMA_TO_ANALYZER = {
45
+ "potential-hangs": {
46
+ tool: "analyzeHangs",
47
+ description: "Parses the hangs table and returns Hang vs Microhang counts plus the longest events. Pair with `topFramesByHangStartNs` to classify main-thread violations.",
48
+ },
49
+ "animation-hitches": {
50
+ tool: "analyzeAnimationHitches",
51
+ description: "Parses the hitches table and reports by-type counts plus the count of user-perceptible (>100ms) hitches.",
52
+ },
53
+ "time-profile": {
54
+ tool: "analyzeTimeProfile",
55
+ description: "Returns top symbols by sample count. Reports a structured workaroundNotice when xctrace SIGSEGVs on heavy unsymbolicated traces.",
56
+ },
57
+ allocations: {
58
+ tool: "analyzeAllocations",
59
+ description: "Returns per-category aggregates (cumulative bytes, allocation count, transient/persistent/mixed lifecycle classification) plus top allocators.",
60
+ },
61
+ "app-launch": {
62
+ tool: "analyzeAppLaunch",
63
+ description: "Returns cold/warm launch type plus per-phase breakdown (process-creation, dyld-init, ObjC-init, AppDelegate, first-frame).",
64
+ },
65
+ };
66
+ /** Pure: parse the trace-toc XML payload into an inspection result. */
67
+ export function parseTraceToc(xml, tracePath) {
68
+ const schemas = [];
69
+ // We use lightweight regex parsing here instead of fast-xml-parser
70
+ // because the TOC XML is simple, well-defined, and the existing
71
+ // parseXctraceXml is row-content focused (parses through schemas).
72
+ // Surfacing only schema metadata + row counts is faster and avoids
73
+ // pulling row payloads into memory for traces that have hundreds of
74
+ // thousands of rows.
75
+ // Match each <table schema="X"> block.
76
+ const tableRegex = /<table\b[^>]*\bschema="([^"]+)"[^>]*>([\s\S]*?)<\/table>/g;
77
+ let match;
78
+ while ((match = tableRegex.exec(xml)) !== null) {
79
+ const name = match[1];
80
+ const body = match[2];
81
+ // Row count = number of <row> tags inside this table.
82
+ const rowMatches = body.match(/<row\b/g);
83
+ const rowCount = rowMatches ? rowMatches.length : 0;
84
+ // Description: schema may carry an `engineering-type` description.
85
+ const descMatch = /<engineering-description>([^<]+)<\/engineering-description>/.exec(body);
86
+ const description = descMatch?.[1]?.trim();
87
+ schemas.push({
88
+ name,
89
+ rowCount,
90
+ ...(description ? { description } : {}),
91
+ });
92
+ }
93
+ schemas.sort((a, b) => b.rowCount - a.rowCount);
94
+ const rowCounts = {};
95
+ for (const s of schemas)
96
+ rowCounts[s.name] = s.rowCount;
97
+ // 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);
100
+ const templateMatch = /<template-name>([^<]+)<\/template-name>/.exec(xml);
101
+ const recordedMatch = /<recorded-when>([^<]+)<\/recorded-when>/.exec(xml);
102
+ const suggestedNextCalls = [];
103
+ for (const s of schemas) {
104
+ if (s.rowCount === 0)
105
+ continue;
106
+ const mapping = SCHEMA_TO_ANALYZER[s.name];
107
+ if (!mapping)
108
+ continue;
109
+ suggestedNextCalls.push({
110
+ tool: mapping.tool,
111
+ args: { tracePath },
112
+ why: `${s.rowCount.toLocaleString()} rows in the ${s.name} schema. ${mapping.description}`,
113
+ });
114
+ }
115
+ return {
116
+ tracePath,
117
+ schemas,
118
+ rowCounts,
119
+ ...(deviceMatch ? { deviceModel: deviceMatch[1].trim() } : {}),
120
+ ...(osMatch ? { osVersion: osMatch[1].trim() } : {}),
121
+ ...(templateMatch ? { templateName: templateMatch[1].trim() } : {}),
122
+ ...(recordedMatch ? { recordedWhen: recordedMatch[1].trim() } : {}),
123
+ diagnosis: buildDiagnosis(schemas, templateMatch?.[1]?.trim()),
124
+ suggestedNextCalls,
125
+ };
126
+ }
127
+ function buildDiagnosis(schemas, templateName) {
128
+ if (schemas.length === 0) {
129
+ return "Trace TOC reports no schemas. The trace may be malformed, empty, or recorded with a custom template the parser does not recognize. Inspect via Instruments.app to confirm.";
130
+ }
131
+ const populated = schemas.filter((s) => s.rowCount > 0);
132
+ const topSchema = populated[0];
133
+ const parts = [];
134
+ if (templateName)
135
+ parts.push(`Template: \`${templateName}\`.`);
136
+ parts.push(`${schemas.length} schema${schemas.length === 1 ? "" : "s"} in the TOC, ${populated.length} with data.`);
137
+ if (topSchema) {
138
+ parts.push(`Heaviest: \`${topSchema.name}\` with ${topSchema.rowCount.toLocaleString()} rows.`);
139
+ }
140
+ if (populated.length === 0) {
141
+ parts.push("All tables are empty. Trace likely recorded zero events; double-check the recording duration and active template.");
142
+ }
143
+ return parts.join(" ");
144
+ }
145
+ export async function inspectTrace(input) {
146
+ const tracePath = resolvePath(input.tracePath);
147
+ if (!existsSync(tracePath)) {
148
+ throw new Error(`Trace bundle not found: ${tracePath}`);
149
+ }
150
+ let fileSize;
151
+ try {
152
+ fileSize = statSync(tracePath).size;
153
+ }
154
+ catch {
155
+ // The bundle is a directory on macOS; stat reports the directory inode
156
+ // size, which is fine for orientation. Failures are non-fatal.
157
+ }
158
+ const result = await runCommand("xcrun", ["xctrace", "export", "--input", tracePath, "--xpath", "/trace-toc/run"], { timeoutMs: 60_000 });
159
+ 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 } : {}) };
169
+ }
170
+ const parsed = parseTraceToc(result.stdout, tracePath);
171
+ return {
172
+ ok: true,
173
+ ...parsed,
174
+ ...(fileSize != null ? { fileSize } : {}),
175
+ };
176
+ }
177
+ // Used by tests to verify the bundle name surfaces correctly.
178
+ export function _basenameForTests(p) {
179
+ return basename(p);
180
+ }
181
+ //# sourceMappingURL=inspectTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspectTrace.js","sourceRoot":"","sources":["../../src/tools/inspectTrace.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorydetective",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "mcpName": "io.github.carloshpdoc/memorydetective",
5
5
  "description": "MCP server for iOS leak hunting and performance investigation. 34 tools across .memgraph and .trace files, 36-pattern retain-cycle classifier with Swift fixTemplate snippets, abandoned-memory diff for KVO/NotificationCenter/cache shapes that escape leaks(1), per-test CI gate (detectLeaksInXCTest + detectLeaksInXCUITest with self-contained HTML reports), main-thread violation classifier on analyzeHangs, single-call build+boot+launch for the macOS 26.x leaks --outputGraph regression, replayScenario + captureScenarioState verify-fix loop, compareTracesByPattern CI gate on hangs/hitches/launch regressions, SourceKit-LSP source bridging. macOS only (depends on leaks(1) and xctrace).",
6
6
  "type": "module",