-
Notifications
You must be signed in to change notification settings - Fork 576
SKILL
name: xcode-api-diff-noise-cleaner description: > Analyze and triage Xcode SDK API diffs between betas for the dotnet/macios binding season. USE FOR: reviewing API diffs, classifying diffs as nothing or actionable, understanding xcode diff folder structure, cleaning up comment-only diffs, checking binding status, running make diff or make all. DO NOT USE FOR: writing C# bindings code (that's a separate task after triage).
Knowledge skill for triaging Xcode SDK header diffs in the macios.wiki repo. Helps classify diffs as actionable API changes vs noise (comments, macros, formatting) and understand the binding status tracking system.
- Reviewing raw framework diffs between Xcode beta versions
- Classifying whether a diff contains real API changes or only noise
- Understanding the xcode diff folder structure and Makefile workflow
- Cleaning up diffs that only contain comment/documentation changes
- Checking or updating the Bindings-Status table
- Running
make difformake allafter Xcode updates
macios.wiki/
├── Makefile # Drives diff generation and status table updates
├── xcode-diff.cs # Script that diffs SDK framework headers
├── update.cs # Script that regenerates the Bindings-Status table
├── xcode{version}/
│ ├── xcode{version}-Bindings-Status.md # Auto-generated status table (NEVER edit directly)
│ ├── b1/ b2/ b3/ rc/ # Per-beta/release diff directories
│ │ ├── iOS/
│ │ ├── tvOS/
│ │ ├── macOS/
│ │ └── MacCatalyst/
│ │ └── {Framework}-{platform}-xcode{ver}-{suffix}.md
{Framework}-{platform}-xcode{version}-{suffix}.md — e.g. AVKit-iOS-xcode26.4-b2.md
An empty diff file contains only #{Framework}.framework with no content below it.
The status table is generated — never edit it directly. Instead, edit the diff files and run make all -j.
| Marker | Meaning |
|---|---|
~~strikeout~~ + *nothing*
|
No new APIs — diff was reviewed and contains no actionable changes |
bold + **???**
|
Has changes, not yet bound |
[PR{number}]({url}) |
Binding work in progress or done |
:warning: |
Tracked via GitHub issue |
- |
Framework not available on that platform |
To mark a diff as "nothing": edit the diff file to contain only the framework header (remove all diff content), then make all -j regenerates the table with strikeout styling.
To claim a binding: add your PR link to the diff file following the existing format.
When reviewing a diff, classify it into one of these categories:
🔍 Read each
+/-line in its real header context first. A changed line can sit inside a block comment, a multi-line HeaderDoc tag, or a\-continued macro — you often can't tell from the diff hunk alone. When in doubt, open the actual installed SDK header at the line numbers in the@@hunk and reconstruct the surrounding context. Misreading a comment line as code (or code as comment) is the most common triage error.
New or modified: classes, protocols, methods, properties, enums, typedefs, constants, or delegate methods. These need C# bindings.
Availability & deprecation changes are also actionable — even when they ride on an attribute or macro rather than a brand-new declaration. A change to when or where an API exists is real binding work (it maps to [SupportedOSPlatform] / [ObsoletedOSPlatform] / [UnsupportedOSPlatform]). Treat as actionable:
-
API_AVAILABLE/API_DEPRECATED/API_UNAVAILABLE/API_DEPRECATED_WITH_REPLACEMENT, and theNS_AVAILABLE*/NS_DEPRECATED*/__attribute__((availability(...)))families - An existing API that gains, tightens, or loses a platform/version (e.g. a property that newly carries
API_AVAILABLE(ios(27.0)))
❌ The macro-redefinition trap. A
#definechange is not automatically noise. If the macro expands to an availability/deprecation/attribute and is applied to public API, redefining it rewrites that whole API surface — actionable. Real case (xcode27.0 b1):ExposureNotificationredefinedEN_API_AVAILABLEfromAPI_AVAILABLE( ios( 12.5 ) )toAPI_DEPRECATED( "No longer supported.", ios( 12.5, 27.0 ) )— one line that deprecated ~75 public symbols framework-wide. Before dismissing any#defineedit, check what it expands to and whether public API uses it.
Category 1: Comment/documentation-only changes
-
/* ... */→/// ...doc comment format rewrites - Typo fixes in comments (e.g. "labelling" → "labeling")
-
@c/@p→ backtick formatting changes - Reformatted multi-line doc comments
- Copyright-year / license-header rewrites
Category 2: Internal/build-system changes
- Preprocessor guard reordering (
#ifdef,#elif,#endif) - Macro renames/edits whose expansion does not change public API (internal-only names, e.g.
TARGET_OS_LINUX_CLOUD→ internal name).⚠️ A macro that expands to availability/deprecation/attributes IS public API — see "The macro-redefinition trap" above. - Version / build-number
#definebumps (e.g.SPRITEKIT_VERSION 40000→41000) - Swift sendability macros (
NS_SWIFT_SENDABLE,NS_SWIFT_UNAVAILABLE) - Header audit pragmas (
#pragma clang assume_nonnull) -
extern "C"guard shuffling -
#include/#importreordering
Category 3: Empty or boilerplate-only
- Diff file has no content below the framework header. Already marked correctly.
- A brand-new header/framework whose diff is only
#import/#includelines, include-guard boilerplate, or an empty umbrella with no public declarations — nothing to bind yet (real cases: AppIntentsTypeSupport, MediaDevice, MetalPerformanceShaders, SpatialPreview, AppManagedFeatures).
⚠️ Mixed diffs: If a diff contains both noise AND real API changes, it is actionable. NEVER clean out the noise portions — the binding author WILL HANDLE everything.
❌ NEVER mark a diff as "nothing" if it contains any new method signatures, property declarations, enum values, class/protocol declarations, or typedef changes — even if surrounded by comment noise.
Only for genuinely hard cases — availability/deprecation shifts, macro redefinitions, brand-new frameworks. Don't apply this to obvious noise or obvious new API.
-
Check prior-season precedent. See how the same or a similar framework was triaged in an earlier season (
xcode26.x/) and stay consistent. Real calls kept ExposureNotification consistent with MetricKit, and treated a boilerplate-only new framework per the AlarmKit-26.0 precedent. - Validate your rule against prior decisions before bulk-marking. Replay your classification over a previous season's already-triaged diffs; if it would mark any real API as "nothing", the rule is too aggressive. (Validating against 233 prior-season files caught zero false negatives in xcode27.0 b1.)
- Rubber-duck the borderline ones with a second model before committing a "nothing".
- Install both the old and new Xcode versions
- Update
Makefilevariables:XCODE_OLD,XCODE_NEW,BRANCH,SUFFIX - Run
make diff -j— generates per-framework, per-platform diff files - Run
make all -j— regenerates the Bindings-Status table - Commit and push all new/updated files
Run make all -j to regenerate the status table, then commit.
Stop analysis when:
- You've classified all diffs requested by the user
- You've determined whether a specific diff is actionable or noise
- The user has the information needed to decide next steps
- Do NOT start writing C# bindings — that's a separate task