dotnet / dotnet/winforms

Track WinForms breaking changes for agent-driven modernization/migration (prototyping & warning)

Open
#14,862 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.