Track WinForms breaking changes for agent-driven modernization/migration (prototyping & warning)
- Dominant language
- C#
- Stars
- 4.9k
- Forks
- 1.1k
- Avg merge
- 1d 13m
- Merged PRs (30d)
- 85
Description
## TL;DR
We need a systematic, **agent-consumable** way to track WinForms breaking changes so that AI agents doing **modernization/migration** work (porting LOB apps from .NET Framework / older .NET to current & upcoming .NET, e.g. .NET 10/11) can reliably avoid subtle regressions.
"Breaking change" here is broader than binary/source compat — it includes **deliberate behavior changes**, **new APIs that make old patterns obsolete**, and — most dangerously — **bug fixes that collide with forgotten customer workarounds**. The information must be available to an agent **before and during** a migration, without polluting the agent's context window.
This is a **coarse guidance / tracking issue** for prototyping and early planning. We deliberately keep the ideas high-level here; we'll dig into details per-approach as we cross each bridge.
---
## Why this matters — the three categories
### 1. Deliberate behavior breaks to improve a feature
We sometimes change behavior on purpose to make a feature better, and we try to **gate** those changes behind opt-in switches — but that's not always fully possible.
- **`Padding` on `TextBox` / `RichTextBox` (.NET 11):** The property becomes accessible (**not** a binary break). Setting it normally has *no effect* — **unless** `VisualStylesMode = Net11`, in which case `Padding` is honored. So the observable behavior depends on an opt-in mode.
- **`FlatStyle`:** Different `FlatStyle` values don't just render a control differently — they can change how much `ClientSize` / real-estate the control claims. That **is** a breaking change for pixel-perfect layout approaches, even when we gate as much as we can.
### 2. New APIs that make existing patterns redundant
Newer, better APIs can make an existing pattern the wrong choice in certain situations.
- **`Control.BeginInvoke` vs. `Control.InvokeAsync`:** Not "broken," but a migration should know when the newer API is the better target — *without* treating this as a scary "breaking change" (that would just create noise).
### 3. Bug fixes that are silent breaking changes
A fix doesn't *sound* like a breaking change — but it can be the worst kind. If a bug existed since .NET Framework, a customer may have shipped a **workaround** and long forgotten it. After migrating to a runtime where the bug is fixed, that workaround may:
- **crash the app** (best case — at least it's noticeable), or
- **silently change behavior** / cause instability down the road (worst case).
> The upstream PR that prompted this — [dotnet/winforms#14826](https://github.com/dotnet/winforms/pull/14826) (PictureBox `OnFrameChanged` handle race / "Error creating window handle") — is a textbook example: a customer who worked around intermittent handle errors could see that workaround misbehave once the underlying race is fixed.
We need this information available to agents **before** a migration/modernization process starts.
---
## What we've already started (prototyping)
- **Analyzers (Roslyn):** recognize "spots" in code that might run into breaking-change situations.
- **MCP Server:** provides context about topics where breaking changes could occur, with some probability weighting.
- **Skills:** cover the most important aspects immediately. ⚠️ **Caveat:** Skills are *not* the right vehicle for **all** of this information — doing so would dilute the agent's context window, which we must avoid.
---
## Additional aspects to consider (from consultation)
The following were gathered in WinForms Team <--> LLM consultation with **Opus 5.0**, **GPT Sol** and **Grok** as additional angles worth keeping in mind while prototyping. Intentionally coarse — not a design.
### Single source of truth
- Treat **Analyzers, MCP, and Skills as *views*, not authors.** Back them with one versioned, machine-readable catalog of hazards with **stable IDs** (e.g. `WF-BRK-####`) referenced from analyzer diagnostics, MCP payloads, and PR descriptions. Hand-maintaining three parallel narratives will fork within weeks.
### Classification (avoid alert fatigue)
- Separate **compatibility risks** from **bug-workaround hazards** from **modernization opportunities** (`InvokeAsync`). Treating obsolescence as a breaking change creates noise.
- Score **potential impact**, **applicability likelihood**, and **detection confidence** *separately*. A severe-but-uncertain risk should prompt *investigation*; a high-confidence deterministic finding may justify a fix. Avoid severity inflation.
### Applicability & versioning
- Model applicability as **version ranges + conditions** (opt-in switches, `AppContext`/runtime config, target framework, DPI, theme, designer vs runtime) — **not** an explicit N×N source→target matrix.
- Capture **unknown configuration** explicitly ("switch state could not be determined") and let that drive validation rather than a false diagnosis.
### Retrieval & workflow
- **Don't rely on the agent remembering to ask** the MCP server. Analyzer findings, project fingerprints, and API usage should **auto-trigger** retrieval.
- Combine a **pre-migration audit** (risk inventory + persistent report) with **just-in-time** inline guidance.
- Keep responses **sparse and layered** — compact summary first, evidence/mitigation on demand — to protect the context window.
### The "forgotten workaround" problem
- Full general detection is **not tractable** — don't promise it. The cheapest useful version is a **curated library of known anti-patterns** that exist *because* of historical bugs (extra `BeginInvoke`, manual padding/pixel compensation, double-set properties, try/catch around fixed NREs).
- When a fix ships **with a switch**, require capturing the **inverse workaround signature** on the same day as the fix PR.
- **Accept silent misses** and advertise the limits, so agents don't assume "no hit = safe."
### Validation
- Capture a **characterization baseline on the *old* runtime before migrating** — an agent can't prove equivalence to behavior that was never recorded.
- Prefer **semantic assertions** (bounds, clipping, text metrics, accessibility tree, event ordering) over pixel-only screenshot diffs, which are brittle across OS/font/theme/DPI.
### Ecosystem reuse
- **Link and specialize** existing .NET breaking-change docs and compatibility analyzers — don't fork them. Our value-add is **WinForms/LOB symptoms + detection hooks**, not restating runtime pages.
### Governance & incentives
- If authoring an entry isn't part of the **existing breaking-change / PublicAPI gate**, it won't happen. Tie it to that gate and keep the tax tiny (~5 required fields for v0: id, versions, symptom, detection, mitigation).
- Every entry gets an **owner + review/expiry**; unowned/stale entries auto-hide from agents after N releases. **Reward narrowing/closing** entries when compat switches land.
### Measuring success
- **Golden LOB fixtures:** before/after apps where an *unguided* agent regresses (layout / async-UI / bug-fix workaround) and a *guided* one doesn't (or flags for a human).
- Drive **zero-impact warnings per migration** down hard; track **time-to-entry** (breaking PR merged → card available) and a quarterly **"would have bitten customers"** catch count.
---
## Non-goals / traps to avoid early
- ❌ **Completeness fantasy** — currency beats coverage; an exhaustive catalog that's stale is a liability.
- ❌ **Skills-as-encyclopedia** — Skills hold *procedure* ("how to migrate X"); the catalog holds *facts* ("X changed in Y").
- ❌ **MCP-as-chatty-oracle** — return structured facts + canonical IDs, not freeform essays an LLM can embroider.
- ❌ **Auto-fixing suspected workarounds** — recommend a targeted comparison / characterization test first.
- ❌ **Explicit N×N version matrix**, boiling the ocean of *all* BCL breaks, or building a perfect ontology before the first fixture win.
---
## Scope of this issue
This is the **coarse guidance issue** for the prototyping and warning phase. Detailed design for each track (Analyzers / MCP / Skills / catalog schema / validation harness) will be split into follow-up issues as we commit to each approach.
Contributor guide
Research direction
No implementation file, test, or entry point is named; start by reviewing the proposed tracks for Analyzers, MCP, Skills, the catalog schema, and the validation harness. This issue is explicitly coarse, so done means selecting and detailing a committed track in a follow-up issue rather than implementing the whole system here.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop, developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100