Releases: carloshpdoc/memorydetective
v1.18.2: /investigate-metrickit prompt + 7th MCP prompt
Post-v1.18.1 follow-up. Adds the /investigate-metrickit MCP prompt (the 7th, completing the prompt surface for the v1.18 MetricKit lane) and syncs the README prompt count which had drifted (stale at 5, actual 7 including /summarize-trace and the new MetricKit prompt). No tool API changes. 757 -> 758 tests (+1).
Added
/investigate-metrickitMCP prompt (7th prompt). Bespoke render (not playbook-backed). Takes apayloadPathargument and produces a ready-to-execute brief: 4 read-priority sections (crashCluster, hangHotspots, cpuExceptions, diskWriteExceptions),suggestedNextCallschain hints intofindCycles/analyzeHangs, and explicit constraints (no symbolication, no direct fix from raw.mxdiagnostic,payloadCount: 0is a valid state). Surfaces in Claude Code as/investigate-metrickit. Prompt count goes from 6 to 7. Asserted viabespoke = ["summarize-trace", "investigate-metrickit"]filter in the playbook-backed coverage test.
Changed
- README prompt count synced. The README listed 5 prompts (stale snapshot from v1.16) when actual count is 7. Updated to enumerate all 7 prompts, including
/summarize-trace(v1.17) and the new/investigate-metrickit.
v1.18.1: docs-only patch syncing README + USAGE with v1.18 MetricKit surface
Docs-only patch. Syncs the npm README + USAGE with the v1.18 surface notes that landed on GitHub right after v1.18.0 was published. No code changes.
Changed
- README "What's new" block leads with v1.18 (MetricKit 42nd tool + audit-close trio). New Examples block "Analyze MetricKit payloads from real-user crashes" with a concrete TestFlight directory aggregation example. New "Production diagnostics (1, v1.18)" API section with full
analyzeMetricKitPayloadsurface description. API "Read & analyze" prefaced with the v1.18 D-02AnalyzeTraceOptionshint.summarizeTracerow gains the D-02 wall-clock-win sentence. - USAGE follow-up requests table adds a "Production diagnostics" sub-section with 4 prompt examples covering
analyzeMetricKitPayload(single payload, directory aggregation,groupByvariants, hang ranking). New end-to-end example "MetricKit production post-mortem" walks through a 47-payload TestFlight investigation mirroring the shape of the existing memgraph example, so the agent flow is consistent across lanes.
v1.18.0: MetricKit (42nd tool) + audit-close trio (D-01 + D-02 + D-03)
Audit-close + MetricKit bet. v1.17 was reliability tightening on the existing surface. v1.18 ships the 42nd MCP tool — analyzeMetricKitPayload, the post-mortem production-diagnostics lane — alongside three audit-close items deferred from v1.17 (open-enum SupportStatusKind, schemaDiscovery cache, real-Apple integration tests). The MCP ecosystem has zero coverage for MetricKit today; this release opens that lane. 701 → 757 tests (+56). 41 → 42 MCP tools.
Added
analyzeMetricKitPayloadMCP tool (42nd,[mg.production]). Ingests Apple MetricKit.mxdiagnosticJSON payloads from real-device TestFlight / App Store builds. Three input forms (single file, directory glob with cross-payload aggregation, raw JSON string). Three actionable outputs:crashCluster(groups by exception type / binary / top frame with configurablegroupBy),hangHotspots(sorted byhangDurationMswith localized-string handling for"5.4 sec"/"20秒"/ etc. — Apple ships localized values),cpuExceptions+diskWriteExceptions(long tail). Each entry includes rawbinaryUUID + offsetIntoBinaryTextSegment + binaryNamefor downstream dSYM lookup. Cross-tool chain hints:_objc_release-style top frame surfaces afindCyclessuggestion,libsqlite3.dylibtop frame surfaces ananalyzeHangschain hint with the main-thread-violation classifier. No symbolication in v1 —analyzeMemgraphevolved through the same staging pattern; dSYM lookup is its own future tool. Simulator does not generate MetricKit payloads (Apple-side limitation); framed as post-mortem analyzer, not live capture. Adds 4 newSupportStatusKindvalues (crash-diagnostics,hang-diagnostics,cpu-exception-diagnostics,disk-write-exception-diagnostics).AnalyzeTraceOptionsinterface insrc/types.ts. New optional second argument shared by every trace-side analyzer carryingdiscoveredSchemas?: Partial<Record<string, string>>. Direct callers leave it unset and pay the one-shot TOC fetch as before; orchestrators (summarizeTrace) populate it once up front so the 6 fan-out analyzers skip their own TOC calls.resolveSchemasForAnalyzerhelper insrc/parsers/schemaDiscovery.ts. Cache-aware schema name resolution: reads the optionalcachedmap when provided (no runner call), falls back to the cold path (fetchDiscoveredSchemas) otherwise, fills gaps with canonical names per family. Same shape as the existing single-familyfetchDiscoveredSchemas, drop-in for the 9 trace analyzers that adopted it.- Local-only integration test suite against real Apple
.tracebundles (src/tools/realApple.integration.test.ts). ReadsMEMORYDETECTIVE_INTEGRATION_TRACESenv var; tests skip silently when unset or fixture missing. 12 tests coverinspectTrace(TOC + metadata + suggestedNextCalls),analyzeHangs(pre + post fix verdicts),analyzeTimeProfile(v1.14 item O regression guard — symbols must be real function names, not the weight column),compareTracesByPattern, andsummarizeTraceend-to-end (also exercises the D-02 cache). Documentation intests/INTEGRATION.md. Fixtures live locally on the maintainer's machine; never committed to git, never shipped via npm.
Changed
SupportStatusKindis now an open enum. Pre-v1.18 it was a closed TypeScript literal union (10 kinds). Adding a kind forced a breaking type change for downstream consumers branching exhaustively. v1.18 switches to theKnownSupportStatusKind | (string & {})pattern: inline literals still get autocomplete + typo detection internally (viaKnownSupportStatusKind), external strings (e.g. the 4 new MetricKit kinds) now type-check without us shipping a new union. Exported runtime constantSUPPORT_STATUS_KINDS(readonly tuple of the 10 strings) so callers can iterate / validate. Existing call sites unchanged. UnblocksanalyzeMetricKitPayload.summarizeTraceruns schema discovery once up front. Pre-v1.18 each of the 6 analyzers it fans out to ran its ownxctrace export --toc. Wall-clock penalty: +600-3000ms on real Apple traces, dominated by xctrace cold-start. v1.18 runsfetchDiscoveredSchemasWithStatusonce at the top with all 7 families needed and passes the cache to every analyzer call via{ discoveredSchemas }. Measured win against the wishlist-tti-device.trace (37 MB Time Profiler) in integration tests: end-to-end summarizeTrace went from ~28s to ~15s per call.- All 9 trace analyzers (
analyzeHangs,analyzeAnimationHitches,analyzeAllocations,analyzeAppLaunch,analyzeTimeProfile,analyzeNetworkActivity,analyzeMemoryFootprint,analyzeEnergyImpact,analyzeLeakTimeline) accept the new optionalAnalyzeTraceOptionssecond argument. Backwards-compatible default: when omitted, behavior is identical to v1.17 (cold-path TOC fetch). No breaking change for any direct caller.
Notes
- The integration test suite is local-only and never runs in CI. CI on Linux continues to skip the 12 tests entirely. To activate locally:
MEMORYDETECTIVE_INTEGRATION_TRACES=~/Desktop npm test. Expected fixtures and the workflow are documented intests/INTEGRATION.md. - The 4 v1.15+ trace analyzers (
analyzeNetworkActivity,analyzeMemoryFootprint,analyzeEnergyImpact,analyzeLeakTimeline) are still synthetic-only at integration level. Add coverage when matching template recordings land in the integration directory. - MetricKit delivery on iOS 18+ has a documented 24-48h delay and a "new bundle id probation" window (Apple Forums thread 766016). The tool surfaces
payloadCount: 0honestly when the directory is empty; do not oversell coverage to users. - The deferred items (D-01 / D-02 / D-03) from
~/Desktop/internal/v1.17-bugs-and-debt.mdare all closed in v1.18. Remaining backlog (Phase 8 v1.9 dSYM symbolication, cross-payload trend analysis on MetricKit,/investigate-metrickitMCP prompt) tracked in~/Desktop/internal/v1.18-roadmap.md§ "Out of scope".
v1.17.1: docs-only patch syncing npm README with the v1.17 surface notes
Docs-only patch. Syncs the npm README + USAGE with the v1.17 surface notes shipped to GitHub right after v1.17.0 was published. No code changes.
Changed
- README leads with the v1.17 reliability headlines; env-var table prefaced with the strtobool truthy parsing rule; macOS 26.x callout cites the new
bundleStatusfield onrecordTimeProfile, thesavedOutsideWatchDirfield onrecordViaInstrumentsApp, and the fault-tolerantinspectTracefallback. Capture / record section renumbered from (3) to (4) with the previously-missingrecordViaInstrumentsApprow.verifyFix+countAlive+inspectTrace+recordTimeProfilerows annotated with their v1.17 surface additions. - USAGE.md follow-up prompts table gained a
verifyFixexample using{ pattern, mode: "exact" }. Troubleshooting recovery list for the macOS 26.x recording wedge documents thesavedOutsideWatchDirAppleScript fallback.
v1.17.0: reliability pass: 14 bug fixes, strtobool env parsing, whitelist match modes, fault-tolerant inspectTrace
Reliability pass. v1.16 closed the macOS 26.x recording gap with recordViaInstrumentsApp. v1.17 sweeps the audit punch list that surfaced after dogfooding: 14 bugs across three tiers, 3 known limitations documented, 3 tech-debt items deferred. The headlines are env-var truthy parsing (every MEMORYDETECTIVE_* boolean now accepts 1 / true / yes / on, was 1-only), a verifyFix whitelist that supports exact / substring / regex modes (was substring-only), the recordViaInstrumentsApp watcher catching saves outside the watch dir, and the inspectTrace fault-tolerant fallback so a wedged 52K bundle no longer throws. 41 MCP tools, 701 tests (+24 vs v1.16).
Fixed
Tier 1 (user-visible)
recordViaInstrumentsAppwatcher misses saves outsidewatchDir(B-01). Pre-v1.17 the tool only watched the filesystem path; users who hit Save in Instruments.app and accepted the default Desktop location would time out even though the trace was on disk. Now queries the running Instruments.app via AppleScript every poll for anydocumentwhose file path was set after the tool started; on first match outsidewatchDirreturns the path withsavedOutsideWatchDir: true. Uses the documentedInstruments.sdeffile of documentaccessor only (no unsupported verbs).verifyFix.expectedAliveClassessupports per-entry mode (B-02). Pre-v1.17 every whitelist entry was matched as a case-insensitive substring. Caller wanting "match exactlyUIRemoteKeyboardWindow, do not matchMyUIRemoteKeyboardWindowWrapper" had no way to express it. Schema now acceptsstring(defaults to substring for backwards compat) or{ pattern: string, mode: "exact" | "substring" | "regex" }. ESLint and Jest both use single-mode matching, but their users have asked for the inverse in tracked issues; we picked the opposite trade-off.MEMORYDETECTIVE_*env booleans accept the strtobool truthy set (B-03). Pre-v1.17 only the literal string1turned a gate on. Users exportingMEMORYDETECTIVE_ALLOW_LAUNCH=trueor=yessaw silent no-op behavior. v1.17 normalizes the five booleans throughparseBooleanEnv, which accepts1 / true / t / yes / y / on(truthy) and0 / false / f / no / n / off(falsy), case-insensitive. Unrecognized values emit a one-time stderr warning per var so the operator knows the setting was ignored. Mirrorsenvalid'sbool()semantics without taking the dependency.maybeOpenInInstrumentschecks bundle viability before opening (B-04). Pre-v1.17 the auto-open path would launch a wedged 52K macOS 26.x stub bundle in Instruments.app, where it presents a Document Missing Template Error dialog the operator has to dismiss. Now probesTrace1.run/MANIFEST.plistbefore callingopen; on missing manifest, skips the open and surfaces the bundle status to the caller. The exportedclassifyBundleOnDisk(tracePath)helper returns"unknown" | "salvageable" | "wedged"for reuse.
Tier 2 (silently sub-optimal)
inspectTracefault-tolerant fallback whenxctrace export --tocfails (B-05). Pre-v1.17 a failed TOC export threw, which broke the entire MCP call. Now returnsok: truewithschemas: [],rowCounts: {},suggestedNextCalls: [], and a diagnosis string naming the 52K macOS 26.x stub pattern so callers can self-diagnose. Throwing is reserved for missing trace paths.schemaDiscovery.fetchDiscoveredSchemasWithStatussurfaces failures (B-06). New sibling offetchDiscoveredSchemasreturns{ schemas, status: "ok" | "failed", reason? }so trace analyzers can include a discovery-failure entry insupportStatus[]instead of silently using canonical schema names against a renamed-schema trace. Emits a one-time stderr warning pertracePath:reason, gated onMEMORYDETECTIVE_SUPPRESS_PLATFORM_ADVISORY. LegacyfetchDiscoveredSchemaskeeps its silent-fallback contract.countByClassWithBytesreports min/max/median for variable-size classes (B-07). Pre-v1.17 we returned the first observedinstanceSizeas canonical for every class. Misled callers inspectingNSData,NSString,CFDatawhose per-instance size is payload-dependent. Now: fixed-size classes return a singleinstanceSizeBytesvalue as before; variable-size classes return{ instanceSizeBytes: median, instanceSizeBytesMin, instanceSizeBytesMax, instanceSizeBytesMedian }.totalBytesunchanged.CountAliveEntrypropagates the spread through per-class and topN paths.analyzeHangs.supportStatus[]always includes both schema entries (B-08). Pre-v1.17 a caller withouthangRisksXmlsaw a single entry, a caller with it saw two. Agent code branching onsupportStatus.find(s => s.kind === "hang-risks")could not distinguish "I did not ask" from "schema absent". Both entries are now always present; the missing-XML path returnsstatus: "not_present"with reason"caller did not provide hangRisksXml".recordTimeProfile.bundleStatusreflects on-disk reality (B-09). NewbundleStatus: "unknown" | "salvageable" | "wedged"field on the response. The timeout path now probesMANIFEST.plistviaclassifyBundleOnDiskso callers branching ontracePath ? "have trace" : "no trace"get an honest signal.countAliveframework-noise filter is configurable (B-10). New inputs:excludeFrameworkNoise: boolean(default true),additionalNoisePatterns?: string[],unsuppressClassPatterns?: string[],noiseAuditMode: boolean. The curated noise list (calibrated for the v1.5 notelet investigation) remains the default. Audit mode returns anoiseAudit[]array listing every filtered class with reason'default-list','additional-pattern', or'kept-by-unsuppress'. User-supplied regex strings compile with a literal-escape fallback on syntax errors.
Tier 3 (edge case / cosmetic)
extractHostparses IPv6 bracket form (B-11).analyzeNetworkActivitywas misreporting hosts like[::1]:443as the empty string. Now strips brackets and splits the port correctly.normalizeBucketpriority fix (B-12).analyzeEnergyImpactwas matching"high"before"foreground"in xctrace's varying-case bucket strings. Reordered to check the named buckets first.- Redundant
t.schema === "memory-footprint"equality removed (B-13).analyzeMemoryFootprintwas double-checking afterdiscoverSchemasalready resolved the family name. analyzeLeakTimelinehandles column-drift gracefully (B-14). When every row is skipped due to missingclassName, returnsstatus: "partial"with a reason naming the column drift instead of silently emitting an empty timeline.
Behavior changes (informational)
- The
MEMORYDETECTIVE_*boolean env vars are now case-insensitively recognized for the strtobool set. Setting=yesor=truenow turns gates on; pre-v1.17 it did not. Operators who deliberately set unrecognized values will see a stderr warning but no behavioral change (unrecognized falls back to default). verifyFix.expectedAliveClassesstring entries continue to behave as case-insensitive substring matches for backwards compat. The new object form{ pattern, mode }is opt-in.- The deprecated
noticeandstatusaliases on trace analyzers stay (will be removed in a future major bump).
v1.16.0: macOS 26.x recording-unblock
The macOS 26.x recording-unblock release. Single feature, single day.
What this fixes
`xcrun xctrace record --time-limit Ns` against iOS simulator targets is broken on macOS 26.x (documented in v1.14). The recording wedges past the time limit, exits when SIGKILL fires, and the resulting `.trace` is missing template metadata. `recordTimeProfile` returns `recordingTimedOut: true` and the auto-open-Instruments / pre-flight UX paths landed in v1.14 mitigate the user experience but the actual automated recording remained blocked.
What v1.16 ships
-
`recordViaInstrumentsApp` MCP tool (41st, `[mg.build]`). The escape hatch. Flow:
- Opens Instruments.app via `open -a Instruments` (fire-and-forget).
- Returns an `instructions[]` array telling the user which template to pick, when to hit Record / Stop / Save, and which directory to save into (configurable `watchDir`).
- Polls `watchDir` every 5 seconds for new `.trace` bundles.
- Treats a new bundle as "saved" when its mtime has been stable for 10 seconds.
- On detection, chains into `inspectTrace` and returns the trace path + schemas + diagnosis.
- Times out after `timeoutSec` (default 600s / 10 min, max 3600s).
Why user-in-loop? Instruments.app's AppleScript surface is minimal: the `document` class exposes `name`, `modified`, `file` properties only - no verbs for start/stop recording or template selection. Documented at `Xcode.app/Contents/Applications/Instruments.app/Contents/Resources/Instruments.sdef`. Full GUI automation is impossible until Apple expands the dictionary.
README + USAGE updates
The macOS 26.x `xctrace record` callout now points at `recordViaInstrumentsApp` as recovery option #1. USAGE.md Troubleshooting list reranked: tool wrapper > older Xcode 26.0 host > manual GUI > physical device > wait for Apple.
Tests + tools
- Suite: 666 -> 677 (+11). New tests cover `snapshotTracesInDir`, `detectNewTraces` filter + sort, `isStable` mtime check, and `buildInstructions` text generation.
- MCP tools: 40 -> 41.
Deferred to v1.17+
- Phase 8 v1.9: dSYM symbolication on `analyzeTimeProfile`.
- Bet #4: `analyzeMetricKitPayload` (.mxdiagnostic ingest).
- Marketplace submissions: PulseMCP, MCP.so.
Full diff: `v1.15.0...v1.16.0`
v1.15.0: schema coverage + verify-fix UX
Schema coverage + verify-fix UX release. 5 items landed on a single day. Suite 626 -> 666 (+40). MCP tools 37 -> 40.
Trace schemas covered
- `analyzeMemoryFootprint` MCP tool (38th). Parses the `memory-footprint` schema. Peak resident / dirty / virtual bytes plus per-sample timeline. The OOM-kill discriminator on iOS. Distinct from `analyzeAllocations` (cumulative malloc bytes by category). Flags peak dirty > 200 MB as approaching jetsam territory.
- `analyzeEnergyImpact` MCP tool (39th). Parses the `energy-impact` schema. Per-sample bucket classification (idle / passive / active / high), aggregate wakeup count, active-state ratio, top-N by energy cost. Reads the OS power-management subsystem directly. Distinct from `analyzeTimeProfile` (CPU sampling).
- `analyzeLeakTimeline` MCP tool (40th). Parses xctrace's leaks schema (the instrument, distinct from `leaks(1)` CLI snapshot). Per-class first-seen-at timestamp, peak instance count, peak bytes, event count. Answers "when in the recording did the leak appear?" which a snapshot cannot.
Synthesis chain
- `summarizeTrace` chains `analyzeNetworkActivity`. Sixth `buildAreaSummary` runs network in parallel. Markdown card gains a Network section + per-host aggregates. `buildHeadline` falls back to the slowest network request (>= 3s) only when hangs / launch / hitches are quiet. `focus: "network"` is a new enum value.
Verify-fix UX
- `replayScenario` captures simulator screenshots per step. New `screenshotDir?: string` input. Each step writes one PNG via `xcrun simctl io screenshot` (no `axe` dependency). DebugSwift-inspired: "what was on screen when this happened?" context for verify-fix loops. `captureSimulatorScreenshot` helper exported. Failures non-fatal.
Type system
- `SupportStatusKind` enum extended with `memory-footprint`, `energy-impact`, `leak-events` to back the three new analyzers.
Deferred to v1.16+
- `recordViaInstrumentsApp` (item G from v1.14 candidates, 8-12h big feature). The AppleScript-driven Instruments.app GUI wrapper. Still the only known reliable trace-recording path on macOS 26.x simulators.
- Phase 8 v1.9: dSYM symbolication on `analyzeTimeProfile`.
- Bet #4: `analyzeMetricKitPayload` (`.mxdiagnostic` ingest).
Full diff: `v1.14.0...v1.15.0`
v1.14.0: trace-side reliability + breadth
Trace-side reliability + breadth release. Single day, 11 items landed across the trace analyzers and MCP surface. Suite 546 -> 626 (+80). MCP tools 36 -> 37.
Trace-side parser fixes
- `inspectTrace` + `summarizeTrace` now work against real Apple traces. The old xpath `/trace-toc/run` returned empty against bundles from `xcrun xctrace record` and Instruments.app; cascaded into `summarizeTrace` reporting "no events detected" even when the trace had 35 hangs. Now uses `xctrace export --toc` + per-schema row-count queries.
- `analyzeTimeProfile` returns real symbol names. Was returning `"1.00 ms"` (the weight column) as every symbol. Now reads the leaf frame's `@_name` from `` with fallback to the binary name for unsymbolicated hex addresses.
Schema coverage expansion
- `analyzeNetworkActivity` MCP tool (37th). Parses the `network-connections` schema. Per-request URL / host / method / status / duration / bytes-in / bytes-out, top-N by duration + by bytes, per-host aggregates.
- `analyzeHangs` reads the `hang-risks` schema alongside `potential-hangs`. Surfaced as `risks[]` + `risksTotals`.
Structural refactors
- Pattern-matching schema discovery. All 5 trace analyzers resolve schema names through a regex map (SCHEMA_FAMILIES) with canonical fallback. Survives future xctrace renames without code changes.
- Unified `supportStatus[]` surface across all 6 trace analyzers (XcodeTraceMCP-pattern). Old `status` / `notice` aliases remain for backwards compat.
macOS 26.x xctrace --time-limit regression UX
- README + USAGE.md callout naming the bug + 4 recovery options.
- `MEMORYDETECTIVE_PREFLIGHT_XCTRACE` env var enables a 2-second probe before the user's actual recording. Cuts failure latency from ~70s to ~8s. Auto-enabled on macOS 26.x simulator attach.
- `MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS` env var enables fire-and-forget `open -a Instruments ` on timeout, opening the partial trace in the Instruments.app GUI.
Memgraph polish
- `countAlive` returns `instanceSizeBytes` + `totalBytes` per class and accepts `sortBy: "totalBytes"`. FLEX-inspired Size view. Validated against real abandoned-memory memgraph: top by totalBytes surfaces 2 MB NSMutableDictionary, 1.3 MB CFString, actionableCounts highlight 800 KB Kernel Pointers + 460 KB CGDataProvider.
- `verifyFix` accepts `expectedAliveClasses[]` whitelist with curated default list of system VCs / views / windows (`UICompatibilityInputViewController`, `UIPredictionViewController`, `UIRemoteKeyboardWindow`, etc.). MLeaksFinder + DebugSwift-inspired UX. Whitelist hits surface in `expectedAlive[]` for transparency without flipping the verdict.
Deferred to v1.15
- `recordViaInstrumentsApp` (item G, 8-12h big feature)
- screenshot during `replayScenario` (item N)
- `summarizeTrace` network chain integration
Full diff: `v1.13.0...v1.14.0`
v1.13.0: summarizeTrace + cross-correlation + /summarize-trace prompt
Trace-depth synthesis differentiator. v1.11 added inspectTrace (discovery), v1.12 added cross-schema correlation inside analyzeHangs. v1.13 ties everything together: one call returns a cross-schema summary card tuned for direct presentation to the user, instead of chaining 5-6 analyzers manually and reasoning over the JSON.
Added
-
summarizeTraceMCP tool (36th tool,[mg.synthesize]). Single call that:- Inspects the TOC via the existing inspectTrace path.
- Chains
analyzeHangs(withincludeStackClassification: trueto auto-classify main-thread violations),analyzeAnimationHitches(with Apple's 100ms perceptible threshold),analyzeTimeProfile,analyzeAllocations,analyzeAppLaunchin parallel via Promise.all guards. - Builds cross-area correlations (Phase 2: hangs+hitches timestamp overlap detection with HIGH/MEDIUM/LOW confidence tiers).
- Returns BOTH a structured per-area result AND a pre-rendered compact markdown card (< 10 KB at default settings, validated by a card-size guard in the unit tests).
The card layout: H1 title, device/OS/template metadata, headline (1-2 sentences naming the biggest user-impact finding ranked by hang>=250ms > launch>1s > perceptible hitches > short hang), per-area sub-sections (suppressed when empty to reduce noise), cross-correlations section with confidence badges, suggested next calls from inspectTrace.
Optional inputs:
focus: "hangs" | "hitches" | "allocations" | "launch" | "all"to bias the summary toward one area;verbose: trueto expand each section's top-N from 5 to 15+ and surface low-confidence correlations inline.Failed analyzers (e.g. xctrace SIGSEGV on time-profile) surface their workaround notice inline; other sections unaffected. Empty schemas don't fail the call.
-
correlateHangsAndHitches()pure cross-correlation helper. Detects hangs whose time windows overlap with animation hitches. When a user sees a hang AND a hitch in the same window, they almost certainly perceived the impact (main-thread block delayed render commits). Confidence tiers:highwhen both events >= 250ms AND overlap span >= 100ms;mediumwhen at least one event >= 250ms;lowwhen both sub-250ms but touching. Results sorted byatSecascending so the markdown card lists correlations in trace order. Allocation-based correlations (hangs+allocations, hitches+allocations) are deferred to v1.14+ because the existinganalyzeAllocationsdoesn't expose per-timestamp allocation rows. -
/summarize-traceMCP prompt (6th prompt). Counterpart to thesummarizeTracetool. Unlike the existing 5 prompts (which wrap multi-step playbooks),/summarize-tracewraps a single tool call. The brief tells the agent to (1) callsummarizeTrace, (2) presentresult.markdownverbatim instead of paraphrasing, (3) offer drill-ins viasuggestedNextCalls. Surfaces the "present the result; don't re-summarize" pattern that agents often get wrong with structured data.
Changed
package.json+server.json: 1.12.0 → 1.13.0.
Test count
523 → 546 (+23): 14 buildHeadline/buildMarkdownCard tests in Phase 1, 9 correlation tests in Phase 2, +0 in Phase 3 (the prompts test was updated, not extended).
v1.12.0: Complete ref-tree propagation (countAlive + findRetainers + verifyFix) + analyzeHangs auto cross-schema correlation
Four-phase patch completing the v1.10 retro §7.2 propagation (countAlive, findRetainers, verifyFix reference-tree integrations) and internalizing the v1.9 cross-schema correlation (analyzeHangs auto-classification). The agent chain analyzeAbandonedMemory → findRetainers → countAlive → verifyFix no longer falls off a cliff after the first call.
Added
-
countAlivereference-tree integration. NewincludeReferenceTree: booleaninput flag (default false preserves v1.11 behavior). When true, spawnsleaks --referenceTree --groupByType --noContentin parallel with the existing cycle pass, merges counts by class name, and surfaces a newactionableCounts[]field filtered viaisFrameworkNoise. ForcountAlive({ className: "AVPlayerItem", includeReferenceTree: true })on the notelet pre-fix memgraph, returnsinstanceCount: 685(substring match captures both AVPlayerItem 342 + AVPlayerItemInternal 343); for the topN path, surfaces AVCMNotificationDispatcher / __NSObserver / AVPlayerItem instead of NSMutableDictionary / CFString noise. New per-classbyCycle+byReferenceTreebreakdown fields when the flag is on. 3 new schema validation tests. -
verifyFixabandoned-memory verdict fallback. v1.11 returnedoverallVerdict: "PASS"with emptypatternResolution[]on the notelet pair (bothleakCount: 0); v1.12 chains internally intoanalyzeAbandonedMemorywhen no cycle patterns fire on either side. NewverdictSource: "cycle-pattern" | "abandoned-memory",freedClasses[],regressionClasses[]fields. Magnitude-dominance heuristic resolves verdict to PASS / PARTIAL / FAIL by comparing the sum of|freed delta|to|growth delta|at a 2x ratio. Notelet pair now returnsverdict: PASSwith diagnosis "Fix verified via abandoned-memory shrinkage: 10,386 instances freed dominates the residual 4,531-instance growth (typically Swift runtime / font cache / ObjC class table)."isFrameworkNoiseextended to flagN bytes into <X 0xADDR> [size]heap-offset entries so the magnitude check doesn't get fooled by partial-allocation noise. 1 new reference-tree filter test. -
findRetainersreference-tree chains. NewincludeReferenceTree: booleaninput flag (default false). When true, spawnsleaks --debug=stacks --debug='<className>$'and parses the per-instance allocation stack output via a newsrc/parsers/leaksDebugStacks.tsparser. Instances sharing the same call-stack fingerprint aggregate into one chain withinstanceCount. Each chain exposescallStack[](ordered frames from dyld root to allocation site),retainers[](unique retainer classes with aggregate counts),exampleAddress(one representative instance), anduserFrame(the deepest non-system frame, surfacing the actual line a developer would inspect). New 11-test parser file. leaks's--debug=predicate restriction documented in the schema description:^is rejected by leaks, only trailing$works. MallocStackLogging caveat documented: Xcode-exported memgraphs may surface fewer chains than the total instance count becauseleaks --debug=stacksonly emits blocks for instances whose allocation stack was recorded. -
analyzeHangscross-schema correlation. v1.9 addedmainThreadViolations[]enrichment via the caller-suppliedtopFramesByHangStartNsmap; v1.12 internalizes it. NewincludeStackClassification: booleaninput flag (default false preserves v1.9 behavior). When true, exports thetime-profileschema in parallel withpotential-hangs, correlates samples to hang windows by timestamp (sample in[hang.startNs, hang.startNs + hang.durationNs]), picks the dominant top frame per hang by aggregate weight, and runsclassifyHangFrame()on it. New purecorrelateTimeProfileToHangs()helper. Caller-supplied maps still take precedence over the auto-correlation. 8 new pure correlation tests covering empty inputs both sides, in/out-of-window, weight tiebreaker, backtrace fallback, multi-hang independence, default-weight handling.
Changed
package.json+server.json: 1.11.0 → 1.12.0.compareTracesByPatterncall sites ofanalyzeHangsnow passincludeStackClassification: falseexplicitly to satisfy the inferredanalyzeHangsinput type (cosmetic; no behavioral change).