Fix MEAI001 leak from experimental RequiresConfirmation in source-generated AIContent contexts - #7659
Merged
jeffhandley merged 1 commit intoJul 27, 2026
Conversation
…erated AIContent contexts
ToolApprovalRequestContent.RequiresConfirmation is [Experimental(MEAI001)] but the
type is a stable, statically-registered [JsonDerivedType] of the [JsonPolymorphic]
AIContent. System.Text.Json's source generator therefore emits the experimental member
into the JSON metadata of any consumer whose JsonSerializerContext includes AIContent
(e.g. List<AIContent>), forcing that consumer to suppress MEAI001 even when it never
uses approval APIs.
Route serialization through a non-experimental internal member: the public property is
now [JsonIgnore] and delegates to internal RequiresConfirmationCore, which carries
[JsonInclude] and [JsonPropertyName("requiresConfirmation")] so the value still
round-trips through the package's default serialization options. This mirrors the
existing pattern on UsageDetails token counts and HostedFileContent.
Also removes the now-unnecessary MEAI001 suppressions from the two Evaluation.Reporting
projects, which had gained them solely because of this leak (PR dotnet#7549).
Adds a no-suppression, MEAI001-as-error regression guard in the Stabilization tests: a
source-generated context over List<AIContent> that fails to compile if any experimental
member leaks back into consumer metadata.
Fixes dotnet#7658
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression where the experimental ToolApprovalRequestContent.RequiresConfirmation member leaked into consumers’ System.Text.Json source-generated AIContent contracts (triggering MEAI001) by gating serialization at the member level while preserving round-tripping through the library’s default serialization path.
Changes:
- Mark
RequiresConfirmationas[JsonIgnore]and route JSON through an internalRequiresConfirmationCoreproperty annotated with[JsonInclude]/[JsonPropertyName]. - Add a stabilization test
JsonSerializerContextrooted atList<AIContent>plus a runtime round-trip test to ensure the generated context is functional. - Remove now-unnecessary
MEAI001suppressions from the two Evaluation.Reporting projects.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/Libraries/Microsoft.Extensions.AI.Stabilization.Tests/AIContentSerializationRegressionTests.cs | Runtime round-trip test to validate the source-generated List<AIContent> context works. |
| test/Libraries/Microsoft.Extensions.AI.Stabilization.Tests/AIContentSerializationRegressionContext.cs | Compile-time guard context to prevent experimental-member leakage into consumer source generation. |
| src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/CSharp/Microsoft.Extensions.AI.Evaluation.Reporting.csproj | Removes MEAI001 suppression that was only needed due to the leak. |
| src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting.Azure/Microsoft.Extensions.AI.Evaluation.Reporting.Azure.csproj | Removes MEAI001 suppression that was only needed due to the leak. |
| src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ToolApprovalRequestContent.cs | Implements the [JsonIgnore] + internal *Core serialization pattern to stop source-gen leakage while preserving default-option round-trip behavior. |
peterwald
approved these changes
Jul 27, 2026
jeffhandley
added a commit
that referenced
this pull request
Jul 27, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Jul 27, 2026
This was referenced Jul 28, 2026
Bump Microsoft.Extensions.AI.Abstractions from 10.7.0 to 10.8.3
TheCodeTraveler/MAUIChatGPTClone#127
Closed
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tracks #7658
Problem
ToolApprovalRequestContent.RequiresConfirmationis[Experimental(MEAI001)], whileToolApprovalRequestContentis a stable, statically registered[JsonDerivedType]of the[JsonPolymorphic]AIContentandInputRequestContenthierarchies. This regression was introduced in 10.8.0 by Add ToolApprovalRequestContent.RequiresConfirmation (#7549).As a result, System.Text.Json source generation emits the experimental member into the JSON metadata for any consumer context that reaches
AIContent, even when the consumer never uses approval APIs:The build emits
MEAI001from source-generated code. Consumers are then forced into a project-wide suppression as the only practical remedy, but the suppression does not remove the member from their generated contract: their externally exposed JSON payloads still include the experimentalrequiresConfirmationfield without an approval-feature opt-in.Fix
ToolApprovalRequestContentis stable; onlyRequiresConfirmationis experimental. Keep the type in the static polymorphic contract, but gate its serialization at the member level using the established pattern used byUsageDetailstoken counts andHostedFileContent:The internal member remains available to the package-owned default serialization path, so persisted conversations continue to round-trip
requiresConfirmation. Consumer source-generated contracts omit the experimental field, and direct use of the public property continues to requireMEAI001opt-in.The two
Microsoft.Extensions.AI.Evaluation.Reportingprojects had gained<NoWarn>$(NoWarn);MEAI001</NoWarn>alongside #7549 solely because of this leak. The fix removes both suppressions; their clean builds demonstrate that they were leak-driven.AbstractionsandAIretain their suppressions because they legitimately use experimental APIs directly.Regression coverage
Adds a no-suppression consumer-boundary guard in
Microsoft.Extensions.AI.Stabilization.Tests:AIContentSerializationRegressionContext.cssource-generatesList<AIContent>. Any experimental member leaking into the contract producesMEAI001at compile time.AIContentSerializationRegressionTests.csconfirms stableList<AIContent>round-trips through that generated context.ToolApprovalRequestContenttests verifyRequiresConfirmationstill round-trips as bothtrueandfalsethroughAIJsonUtilities.DefaultOptionsandAIContentpolymorphism.Validation
Microsoft.Extensions.AI.Stabilization.Tests: 90/90 pass across net472, net8.0, net9.0, and net10.0 without an MEAI001 suppression.Microsoft.Extensions.AI.Abstractions.Tests: 1634 pass; the intended persistence round-trip remains intact.MEAI001in the generatedAIContentSerializationRegressionContext.ToolApprovalRequestContent.g.csacross all four target frameworks.Microsoft Reviewers: Open in CodeFlow