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".