/** * `analyzeMetricKitPayload`: 42nd MCP tool (v1.18). The post-mortem * production-diagnostic lane. * * MetricKit (`MXMetricManager`) delivers `.mxdiagnostic` JSON payloads to a * directory readable by the next launch of the app, on real-device * TestFlight / App Store builds. Devs typically airdrop the file to their * Mac and want a structured summary without uploading to Sentry / * Crashlytics. No MCP server in the ecosystem covers this lane today * (researched 2026-05-17: XcodeBuildMCP, XcodeTraceMCP, Sentry Cocoa SDK * server-side ingestion only — no parser surface for dev tooling). * * This tool is a POST-MORTEM ANALYZER. It does not generate payloads * (simulator does not support MetricKit — Apple-side limitation). Inputs * are existing `.mxdiagnostic` files or directories of them. * * Three actionable outputs, in priority order: * 1. `crashCluster` — group by exception type + top frame, count, list * affected app builds. * 2. `hangHotspots` — sorted by hang duration with the top frame. * 3. `cpuExceptions` + `diskWriteExceptions` — long tail of resource * regressions. * * No symbolication in v1: ship raw `binaryUUID + offsetIntoBinaryTextSegment * + binaryName`. dSYM lookup is the Phase 8 v1.9 deferred item, separate * tool, separate release. Mirrors the staging pattern `analyzeMemgraph` * evolved through. */ import { z } from "zod"; import { type MetricKitPayload } from "../parsers/metricKit.js"; import type { NextCallSuggestion, SupportStatus } from "../types.js"; export declare const analyzeMetricKitPayloadSchema: z.ZodObject<{ payloadPath: z.ZodOptional; payloadDir: z.ZodOptional; payloadJson: z.ZodOptional; topN: z.ZodDefault; groupBy: z.ZodDefault>; }, "strip", z.ZodTypeAny, { topN: number; groupBy: "binary" | "top-frame" | "exception-type"; payloadPath?: string | undefined; payloadDir?: string | undefined; payloadJson?: string | undefined; }, { topN?: number | undefined; payloadPath?: string | undefined; payloadDir?: string | undefined; payloadJson?: string | undefined; groupBy?: "binary" | "top-frame" | "exception-type" | undefined; }>; export type AnalyzeMetricKitPayloadInput = z.infer; export interface CrashClusterEntry { /** Cluster key: exceptionType (numeric), signal (numeric), and (when groupBy=binary|top-frame) the binary or top frame string. */ clusterKey: string; exceptionType?: number; signal?: number; terminationReason?: string; topFrame: string; /** Number of crash diagnostics that fell into this cluster across all payloads. */ occurrences: number; affectedBuilds: string[]; /** One representative frame so the caller has the raw `binaryUUID + offset` to symbolicate later if they have a dSYM. */ sample: { binaryUUID?: string; binaryName?: string; offsetIntoBinaryTextSegment?: number; }; /** Per-cluster schema version: when payloads in this cluster used multiple `version` values, all are listed. */ payloadVersions: string[]; } export interface HangHotspotEntry { hangDurationMs: number; topFrame: string; binaryName?: string; /** sampleCount on the deepest-root frame — Apple uses this to weight stacks. */ sampleCount?: number; /** Build identifier the diagnostic came from. */ appBuildVersion?: string; } export interface CpuExceptionEntry { totalCPUTimeMs?: number; totalSampledTimeMs?: number; cpuExceptionLimit?: string; topFrame: string; appBuildVersion?: string; } export interface DiskWriteExceptionEntry { writesCausedMB?: number; topFrame: string; appBuildVersion?: string; } export interface AnalyzeMetricKitPayloadResult { ok: boolean; /** Number of `.mxdiagnostic` files (or in-memory payloads) ingested. */ payloadCount: number; timeRange?: { start: string; end: string; }; crashCluster: CrashClusterEntry[]; hangHotspots: HangHotspotEntry[]; cpuExceptions: CpuExceptionEntry[]; diskWriteExceptions: DiskWriteExceptionEntry[]; /** Per-section availability so callers can branch without inspecting counts. */ supportStatus: SupportStatus[]; /** Plain-English headline. */ diagnosis: string; /** Cross-tool chain suggestions (e.g. db-lock-shaped hang -> analyzeHangs hint when caller has a trace). */ suggestedNextCalls: NextCallSuggestion[]; } /** * Pure: aggregate one or more parsed payloads into the analyzer result. * Split from the I/O wrapper so unit tests can drive it from JSON strings * without touching the filesystem. */ export declare function analyzePayloads(payloads: MetricKitPayload[], options: { topN: number; groupBy: "exception-type" | "binary" | "top-frame"; }): AnalyzeMetricKitPayloadResult; export declare function analyzeMetricKitPayload(input: AnalyzeMetricKitPayloadInput): Promise;