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 (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.
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.
PaddingonTextBox/RichTextBox(.NET 11): The property becomes accessible (not a binary break). Setting it normally has no effect — unlessVisualStylesMode = Net11, in which casePaddingis honored. So the observable behavior depends on an opt-in mode.FlatStyle: DifferentFlatStylevalues don't just render a control differently — they can change how muchClientSize/ 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.BeginInvokevs.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:
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
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
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.