| name | api-rule-gap-classification |
| description | Use for MigrateToWinUI rule-gap classification work: assign API gap rows to AW2U/WP2U families, distinguish direct/equivalent/pattern/manual/unsupported/out-of-scope classifications, review promotion gates, and check coverage without conflating classification with safe rewrite automation. |
API Rule Gap Classification
Use this skill when turning API gap output into rule-family decisions, seed classifications, or rule-pack work. The goal is auditable 100.0% classification coverage for accepted source catalogs while keeping automated rewrite coverage separate.
References
- Rule family taxonomy:
specs/001-migration-core/rule-family-catalog.md
- Remaining work catalog and phase plan:
specs/001-migration-core/remaining-work.md
- API surface contract:
specs/001-migration-core/contracts/api-surface.md
- Rule-pack schema:
specs/001-migration-core/contracts/rule-pack.schema.json
- CLI commands:
README.md, specs/001-migration-core/contracts/cli.md
- Built-in rules and seed catalog code:
src/MigrateToWinUI.Core/
Classification Contract
Every scanned source API must end with exactly one effective classification:
Direct: target API has the same effective role; target symbol is required.
Equivalent: target API is close but needs namespace, type, or usage adjustment; target symbol is required.
Pattern: migration requires a documented C#/XAML/project pattern; pattern id is required.
ManualReview: tool can identify the source API, but a human must choose target behavior; diagnostic id is required.
Unsupported: no supported WinUI/Uno replacement for the target profile; diagnostic id is required.
OutOfScope: intentionally excluded; explicit rationale is required.
Use AW2U ids only for Avalonia source semantics and WP2U ids only for WPF source semantics. Do not reuse an AW2U id for WPF or renumber existing ids.
Family Selection
Choose the most specific family before using an umbrella manual/unsupported row.
Avalonia family ranges:
AW2U0001-AW2U0099 project-lifetime-bootstrap
AW2U0101-AW2U0199 xaml-controls-layout
AW2U0201-AW2U0299 binding-data-context
AW2U0301-AW2U0399 property-custom-controls
AW2U0401-AW2U0599 styles-templates-resources
AW2U0601-AW2U0649 platform-services
AW2U0650-AW2U0674 dialogs-windowing
AW2U0675-AW2U0699 input-commands
AW2U0701-AW2U0749 rendering-composition
AW2U0750-AW2U0799 animations-transitions
AW2U0801-AW2U0849 data-controls-collections
AW2U0850-AW2U0899 interop-native
AW2U0901-AW2U0999 manual-unsupported-out-of-scope
WPF family ranges:
WP2U0001-WP2U0099 wpf-project-bootstrap
WP2U0101-WP2U0199 wpf-xaml-controls-layout
WP2U0201-WP2U0299 wpf-bindings
WP2U0301-WP2U0399 wpf-dependency-routed
WP2U0401-WP2U0599 wpf-styles-templates-resources
WP2U0601-WP2U0669 wpf-platform-windowing-dialogs
WP2U0670-WP2U0699 wpf-commands-input
WP2U0701-WP2U0799 wpf-rendering-composition
WP2U0801-WP2U0899 wpf-documents-media-interop
WP2U0901-WP2U0999 wpf-manual-unsupported-out-of-scope
Workflow
Generate current gaps from pinned artifacts or task-local catalogs:
dotnet run --project src/MigrateToWinUI.Cli -- api gaps --source out/api/source.json --matches out/api/source-to-target.matches.json --rules builtins --out out/api/source-to-target.gaps.json --format json
dotnet run --project src/MigrateToWinUI.Cli -- api coverage --matches out/api/source-to-target.matches.json --rules builtins --out out/api/source-to-target.coverage.json --format json
Inspect unclassified and unknown rows:
rg -n '"classification": "Unknown"|"unclassifiedApiCount"|"suggestedRuleFamily"|"ruleSpecIds": \\[\\]' out/api/source-to-target.gaps.json out/api/source-to-target.coverage.json
For each gap row, record:
- Source framework and diagnostic prefix.
- Source symbol id and symbol shape.
- Chosen family and id range.
- Classification.
- Target symbol, pattern id, diagnostic id, rule id, or out-of-scope rationale.
- Automation posture:
SafeRewrite, DiagnosticOnly, Manual, or None.
- Notes that explain lossy behavior or target-profile differences.
Decision Rules
Prefer Direct only when source and target behavior are equivalent enough that no source-usage transformation is needed beyond referencing the target API.
Use Equivalent when the target API exists but needs a deterministic adjustment, such as namespace/type substitution, with no hidden semantic decision.
Use Pattern when source semantics require code, XAML, project, service-abstraction, lifetime, resource, binding, rendering, or target-profile guidance.
Use ManualReview when the API is identifiable but the right migration depends on app design, target platform capabilities, or runtime behavior not available from static evidence.
Use Unsupported when the target profile cannot support the source API. Include target profile in the note when support differs between WinUI 3 and Uno.
Use OutOfScope only when the API is intentionally excluded from migration scope, not as a placeholder for unknown work.
Promotion Gates
Manual-review to pattern-backed classification requires:
- Deterministic source API symbol or XAML usage shape.
- Target WinUI/Uno behavior documented for
winui3, uno, or both.
- Lossy behavior and target-specific behavior called out.
- Diagnostic id, pattern id, or rule id linked.
- Tests or fixture evidence proving the row appears in gap/coverage output.
Pattern-backed classification to safe rewrite requires:
- Preconditions machine-checkable by Roslyn, XAML parsing, MSBuild metadata, or deterministic text spans.
- Ambiguous cases excluded with diagnostics.
- Before/after golden output.
- Negative tests proving unsafe cases are not rewritten.
- Target XAML/project validation when compiled XAML or project files change.
Do not promote BAML-derived XAML or decompiler-generated code to safe rewrite without binary-lane provenance and explicit validation.
Output Checks
Before calling classification work complete:
api coverage reports no unclassified source APIs.
api gaps summary has unclassifiedApiCount equal to 0.
- Every manual/unsupported row has
AW2U or WP2U rule evidence or an explicit rationale.
- Umbrella families contain only rows that cannot yet be split into a more specific family.
- Automation totals are reported separately from classification totals.
- Rescan-added and rescan-changed APIs are either classified or left as explicit follow-up blockers.
Reporting
Summaries should list counts by source framework, family, classification, and automation posture. Call out the next smallest rule-family gap rather than recommending broad rewrites.