Skip to content

[automated] Merge branch 'main' => 'net10.0' - #36400

Closed
github-actions[bot] wants to merge 917 commits into
net10.0from
merge/main-to-net10.0
Closed

[automated] Merge branch 'main' => 'net10.0'#36400
github-actions[bot] wants to merge 917 commits into
net10.0from
merge/main-to-net10.0

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

I detected changes in the main branch which have not been merged yet to net10.0. I'm a robot and am configured to help you automatically keep net10.0 up to date, so I've opened this PR.

This PR merges commits made on main by the following committers:

  • PureWeen
  • jfversluis
  • kubaflo
  • devanathan-vaithiyanathan
  • dependabot[bot]
  • akoeplinger
  • jonathanpeppers
  • T-Gro
  • TamilarasanSF4853
  • sheiksyedm
  • JanKrivanek
  • arpitjain099
  • davidortinau
  • dotnet-maestro[bot]
  • github-actions[bot]
  • sbomer
  • Ahamed-Ali
  • mattleibow
  • Copilot
  • CathyZhu0110
  • Vignesh-SF3580
  • StephaneDelcroix
  • Oxymoron290
  • mmitche
  • rmarinho
  • pictos
  • lewing
  • noiseonwires
  • jpd21122012
  • rolfbjarne
  • dartasen
  • LogishaSelvarajSF4525
  • NafeelaNazhir
  • simonrozsival
  • praveenkumarkarunanithi

Instructions for merging from UI

This PR will not be auto-merged. When pull request checks pass, complete this PR by creating a merge commit, not a squash or rebase commit.

merge button instructions

If this repo does not allow creating merge commits from the GitHub UI, use command line instructions.

Instructions for merging via command line

Run these commands to merge this pull request from the command line.

git fetch
git checkout main
git pull --ff-only
git checkout net10.0
git pull --ff-only
git merge --no-ff main

# If there are merge conflicts, resolve them and then run git merge --continue to complete the merge
# Pushing the changes to the PR branch will re-trigger PR validation.
git push https://github.com/dotnet/maui HEAD:merge/main-to-net10.0
or if you are using SSH
git push git@github.com:dotnet/maui HEAD:merge/main-to-net10.0

After PR checks are complete push the branch

git push

Instructions for resolving conflicts

⚠️ If there are merge conflicts, you will need to resolve them manually before merging. You can do this using GitHub or using the command line.

Instructions for updating this pull request

Contributors to this repo have permission update this pull request by pushing to the branch 'merge/main-to-net10.0'. This can be done to resolve conflicts or make other changes to this pull request before it is merged.
The provided examples assume that the remote is named 'origin'. If you have a different remote name, please replace 'origin' with the name of your remote.

git fetch
git checkout -b merge/main-to-net10.0 origin/net10.0
git pull https://github.com/dotnet/maui merge/main-to-net10.0
(make changes)
git commit -m "Updated PR with my changes"
git push https://github.com/dotnet/maui HEAD:merge/main-to-net10.0
or if you are using SSH
git fetch
git checkout -b merge/main-to-net10.0 origin/net10.0
git pull git@github.com:dotnet/maui merge/main-to-net10.0
(make changes)
git commit -m "Updated PR with my changes"
git push git@github.com:dotnet/maui HEAD:merge/main-to-net10.0

Contact .NET Core Engineering (dotnet/dnceng) if you have questions or issues.
Also, if this PR was generated incorrectly, help us fix it. See https://github.com/dotnet/arcade/blob/main/.github/workflows/scripts/inter-branch-merge.ps1.

SubhikshaSf4851 and others added 30 commits April 22, 2026 12:07
<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Root Cause : 
The root cause was the absence of a proper property mapping and update
mechanism for the `Background` property in the Windows `WebViewHandler`.
As a result, the MAUI `WebView.Background` value was never applied to
the native `WebView2`, leading to the inability to override the
background color.

### Description of Change
<!-- Enter description of the fix in this section -->
**WebView background color support (Windows):**
* Added a new internal method `MapBackground` in
`WebViewHandler.Windows.cs` to map the `Background` property for
`WebView` controls. This method calls a new extension method to update
the background color on the platform view.
* Registered the `Background` property mapping in the handler's property
mapper for Windows in `WebViewHandler.cs`.
* Implemented the `UpdateBackground` extension method in
`WebViewExtensions.cs` to set the `DefaultBackgroundColor` of the
Windows `WebView2` control based on the provided `Background` value, and
to adjust the preferred color scheme accordingly.
* Ensured the background color is updated when the `WebView2` control is
initialized in `WebViewHandler.Windows.cs`.

**Testing:**
* Added a new test page (`Issue34518.cs` in `TestCases.HostApp`) to
demonstrate and verify that the background color of a `WebView` can be
set to green on Windows.
* Added a corresponding UI test (`Issue34518.cs` in
`TestCases.Shared.Tests`) to validate that the background color is
correctly applied.

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #34518

### Tested the behavior on the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

| Before Issue Fix | After Issue Fix |
|------------------|----------------|
| <img width="1524" height="787" alt="BeforeFixWindows"
src="https://github.com/user-attachments/assets/1d726fbf-83a4-487a-8224-d5e55fea09e5"
/> | <img width="1487" height="813" alt="AfterFixWindows"
src="https://github.com/user-attachments/assets/765449b6-a0b2-4bba-925a-9b29b4303dfb"
/> |
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
…#33090)

### Issue Detail
Shell.TabBarIsVisible does not update dynamically when set on
ShellContent, even when using binding.

### Root Cause
There were two gaps in the existing implementation:

1. Initial value: In ShellItem.ShowTabs, the effective value of
TabBarIsVisible was resolved starting from displayedPage — it never
walked up to ShellContent. So if the property was only set on a
ShellContent (not on the page), it was silently ignored.

2. Dynamic updates: In
ShellElementCollection.BaseShellItemPropertyChanged, only
BaseShellItem.IsVisible changes triggered visibility re-evaluation.
Changes to Shell.TabBarIsVisibleProperty on ShellContent were not
handled at all, so bindings on ShellContent had no effect at runtime.

### Description of Change
src/Controls/src/Core/Shell/ShellItem.cs — IShellItemController.ShowTabs
getter:
- Retrieves the current ShellContent via CurrentItem?.CurrentItem
- If TabBarIsVisible is explicitly set on the ShellContent, passes
shellContent (instead of displayedPage) as the element to
GetEffectiveValue
- This ensures ShellContent-level values take priority in the lookup
chain

src/Controls/src/Core/Shell/ShellElementCollection.cs —
BaseShellItemPropertyChanged:

- Added an else if branch to handle Shell.TabBarIsVisibleProperty
changes on ShellContent senders
- On change: walks up to the parent Shell, gets the currently displayed
page, and checks whether that page belongs to the changed ShellContent
- If it does and the values differ, calls
Shell.SetTabBarIsVisible(displayedPage, shellContentValue) to sync the
value to the active page, triggering a UI refresh

### Tested the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Issues Fixed

Fixes #32994

### Screenshots

**Android:**
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/e9aa1670-d320-45fa-815a-97ec5f38f877">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/0964c0df-b73c-4d04-9d9a-86ebf5745b32">)
|

**iOS:**
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/8a60ef4e-b94b-48dc-b998-be74274e6962">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/12e9db24-1d4b-4156-ac01-e5f2c1fb1185">)
|
…when re-selecting same item (#31591)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

The selected item background color is not applied in Android platform. 
        
### Root Cause:

On Android, UpdateMauiSelection sets ItemsView.SelectedItem to the newly
tapped item. When the ItemsSource contains duplicate values (e.g., all
string "a" items), assigning the new item doesn't change SelectedItem
because the value is equal to the previous one. As a result,
VisualStateManager.GoToState() is never called on the new item's
TemplatedItemViewHolder, so the Selected visual state is never applied.

### Description of Change:

In SelectableItemsViewAdapter.UpdateMauiSelection (Android), when
SelectionMode.Single is in use:

- Before setting SelectedItem, the previous value is captured.
- After setting, if the previous and new values are equal (duplicate
item), the fix manually forces the visual state update:
 i)  Calls ClearPlatformSelection() to deselect all ViewHolders.
ii) Sets IsSelected = true on the ViewHolder at the tapped position,
which triggers OnSelectedChanged() →
VisualStateManager.GoToState("Selected").

This ensures the visual state is refreshed even when SelectedItem
doesn't change.

**Tested the behavior in the following platforms.**

- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #20062  

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/772b5b60-ac4c-4512-a8ee-fbf4d3bbe8cb"
Width="300" Height="600"> | <Video
src="https://github.com/user-attachments/assets/5ddd2eb9-cd40-48d1-87ba-a1d2dec4eae1"
Width="300" Height="600"> |
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

Corrects style inheritance in Style.ApplyCore by unapplying the base
style before reapplying it.

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #31280

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------

Co-authored-by: Shane Neuville <5375137+PureWeen@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>
…b bar, and Locked flyout position (#32701)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issues

- Flyout menu items do not update correctly for RTL direction
- Tab bar and its content do not update correctly for RTL direction
- When flyout behavior is in locked state, flyout X position is not
aligned correctly for RTL direction

### Root Cause

- Flow direction is not set for menu item cells of UITableViewCell,
flyout header, footer, tab bar items and their content
- Flyout X position is incorrectly calculated in flyout locked state for
right-to-left direction

### Description of Changes

- Ensured that Shell flyout headers and footers inherit the parent
Shell's FlowDirection when set to MatchParent, and applied the flow
direction to their platform views
- Updated the flow direction for Shell section views, navigation bars,
and tab bars to respect the Shell's flow direction, including handling
cases where tab bar items are present
- Modified ShellTableViewSource to inherit flow direction from Shell for
menu item cells when set to MatchParent, and applied the correct flow
direction to the platform view
- Adjusted flyout positioning logic in RTL mode to correctly handle the
Locked flyout behavior


Validated the behaviour in the following platforms
- [x] Android
- [x] Windows ,
- [x]  iOS, 
- [x] MacOS

### Issues Fixed

Fixes #32419 

### Output 

**iOS**

|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/50d731bc-3f19-4fd5-af7e-425bb7dae279"
>| <video
src="https://github.com/user-attachments/assets/40a95d05-edcb-42c3-b3f0-16c8c78fdaea">|

**macOS**
|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/df45b88f-735d-4ea0-bd1a-9592b05ab7ee"
>| <video
src="https://github.com/user-attachments/assets/a681d6d1-8b34-4175-ab7a-01d5642d8fad">|

---------
…efore layout completes (#33207)

### Root Cause
MAUI intentionally sets `SetClipChildren(false)` on layout containers to
allow child views to render outside their bounds for visual effects such
as shadows. However, on Android, a hardware-accelerated WebView renders
immediately when it is added to the view hierarchy—before the layout
system computes its final bounds. When combined with disabled clipping,
the WebView briefly renders at full-screen size before being constrained
to its actual layout bounds, causing a visible flash that is more
noticeable on slower devices.
 
### Description of Change
To prevent the initial full-screen flash, `ClipBounds` is applied to
constrain WebView rendering to its allocated bounds. The WebView is
initialized with an empty clip (`0×0`) to block rendering before layout
completes. Once layout is finalized, the clip is updated to the actual
bounds, allowing rendering only at the correct size.
Because WebView rendering is hardware-accelerated and occurs
asynchronously before layout callbacks are invoked. Using ClipBounds
ensures the WebView never renders outside its intended bounds,
eliminating the visual flash.

### Issues Fixed
Fixes #31475 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

**Note:**
Visual timing bugs occurring between render frames cannot be detected by
automated tests, as the flash happens before layout completes and no
measurable state captures the momentary incorrect render.

### Output Video
HybridWebView - Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2655be68-a124-4f45-9a96-baf79862050a">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/5b922a54-8001-4e3b-ba63-a41764eca785">|

WebView - Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/09568286-7dcb-43d1-a5b5-3591fd56aa89">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/60f516db-91c5-4c6b-9336-389b257487d1">|

---------

Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
… FlyoutPage Detail (#31931)

### Issue Details:

On Android, the OnNavigatedTo method of the content page is being called
twice when Detail page of FlyoutPage is navigation page.
       
### Root Cause:

The duplicate invocation occurs due to two separate triggers:
 
i) Setting the Detail property of the FlyoutPage explicitly calls
OnNavigatedTo.
ii) The OnHandlerChangedCore method also triggers OnNavigatedTo. This
method is invoked from the overridden OnFragmentResumed in
StackNavigationManager, which is itself called from the native Android
framework during the fragment lifecycle.
 
As a result, both the framework-level and platform-level calls cause
OnNavigatedTo to execute, leading to the observed duplication.

### Description of Change:

To prevent duplicate calls, the OnNavigatedTo method is not invoked
again if the same page has already been navigated to. This check is
handled within the SendNavigatedTo method of the Page class.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #23902   

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/8a960e61-1929-47e2-8ffc-5eb91ab38df3"
Width="300" Height="600"> | <Video
src="https://github.com/user-attachments/assets/5a8ec689-42ca-4fb4-9194-a05217698b6a"
Width="300" Height="600"> |
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

Corrects mapping logic for LineHeight, TextDecorations, and
CharacterSpacing to apply to HTML labels. Updates iOS handler to refresh
these properties when TextType changes. Adds test case for Issue22197 to
verify correct rendering of HTML labels with these properties.

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #22193
Fixes #22197

|Before|After|
|--|--|
|<img
src="https://github.com/user-attachments/assets/2b3e0d9f-4664-4b34-ac9f-c8900fdc39b8"
width="300px"/>|<img
src="https://github.com/user-attachments/assets/57fec4ed-a4b0-4ea7-af79-d18b4fa6c5e2"
width="300px"/>|

|Before|After|
|--|--|
|<img
src="https://github.com/user-attachments/assets/c62754f3-3d62-4e3d-b457-75a0bbd0ffe8"
width="300px"/>|<img
src="https://github.com/user-attachments/assets/84b372f0-6c02-4ecd-a91d-98072cdbd808"
width="300px"/>|

---------
### Issues Fixed

Fixes #26846

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/4be00a9f-200b-4d84-9826-51b464a89e24"
width="300px"/>|<video
src="https://github.com/user-attachments/assets/831e2554-4739-42b6-8758-cc49b6ee5449"
width="300px"/>|

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could <a
href="https://github.com/dotnet/maui/wiki/Testing-PR-Builds">test the
resulting artifacts</a> from this PR and let us know in a comment if
this change resolves your issue. Thank you!

## Description

Implements the Windows Maps handler using the new WinUI 3 `MapControl`
(Windows App SDK 1.8+), which is backed by Azure Maps. Previously, all
Windows `MapHandler` methods threw `NotImplementedException`.

**No new public API surface** — this change only provides platform
implementations behind already-shipped APIs. `PublicAPI.Unshipped.txt`
is empty. This makes it suitable for a servicing release.

## What's implemented

| Feature | Status | Implementation |
|---------|--------|----------------|
| MoveToRegion | ✅ | `map.setCamera()` via WebView2 JS (workaround for
[microsoft-ui-xaml#9490](microsoft/microsoft-ui-xaml#9490))
|
| MapType (Street/Satellite/Hybrid) | ✅ | `map.setStyle()` via WebView2
JS |
| IsTrafficEnabled | ✅ | `map.setTraffic()` via WebView2 JS |
| IsScrollEnabled | ✅ | `map.setUserInteraction()` via WebView2 JS |
| IsZoomEnabled | ✅ | `map.setUserInteraction()` via WebView2 JS |
| Pins (add/clear/click) | ✅ | `MapIcon` on `MapElementsLayer` |
| Animated navigation | ✅ | Ease animation (300ms) |

## What's NOT implemented (no feature parity)

These features are **no-op** on Windows due to WinUI 3 `MapControl`
limitations. They don't throw — they silently do nothing, matching the
pattern other platforms use for unsupported features.

| Feature | Reason |
|---------|--------|
| IsShowingUser | No built-in user location display |
| Polylines/Polygons/Circles | `MapElementsLayer` only supports
`MapIcon` |
| Pin Labels/InfoWindows | `MapIcon` has no label or info window support
|
| Map background click | `MapElementClick` only fires for `MapElement`
clicks |

## Architecture

The WinUI 3 `MapControl` internally wraps Azure Maps in a `WebView2`.
Several dependency properties (like `Center`) don't reliably propagate
to the JS layer
([microsoft-ui-xaml#9490](microsoft/microsoft-ui-xaml#9490)).
This handler works around that by:

1. Discovering the internal `WebView2` child via
`VisualTreeHelper.GetChild()`
2. Waiting for `NavigationCompleted` to know Azure Maps JS is ready
3. Calling Azure Maps JS APIs directly (`map.setCamera()`,
`map.setStyle()`, etc.)

## Authentication

Uses the existing Essentials pattern — no new API needed:

```csharp
builder.ConfigureEssentials(e => e.UseMapServiceToken("YOUR_AZURE_MAPS_KEY"));
```

Get a key from the [Azure Portal](https://portal.azure.com) → Azure Maps
account → Authentication.

## Files changed

- `MapHandler.Windows.cs` — Full handler implementation (was all
`NotImplementedException`)
- `MapPinHandler.Windows.cs` — Pin handling via `MapIcon`
- `MapElementHandler.Windows.cs` — Documented no-op stubs for shapes
- `AppHostBuilderExtensions.cs` — Updated XML docs to reflect Windows
support

## TODO for .NET 11

Refactor setup/cleanup into `ConnectHandler`/`DisconnectHandler`
overrides to match iOS/Android pattern (avoided here to prevent new
PublicAPI entries).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Root Cause : 
The UpdateCharacterSpacing method only applied character spacing to the
main text content of the TextBox
### Description of Change
Enhanced the UpdateCharacterSpacing method to apply character spacing to
placeholder text also.
<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #30071 

### Tested the behaviour in the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

### Screenshot

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/4100ddd5-6c48-437a-9b9e-cf6cf6f133fc">
| <img
src="https://github.com/user-attachments/assets/78e8a98e-f5ba-452f-bb38-4bf905eeccc5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
…ta in pages within Shell sections (#29545)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root cause

The issue occurs because SearchHandler references don't update properly
during ShellSection page navigation. While SearchView instances are
intentionally preserved for performance, the system failed to
synchronize the SearchHandler reference when transitioning between
pages. This caused search functionality to continue using the previous
page's configuration instead of adopting the current page's settings,
resulting in inconsistent search behavior and incorrect UI elements.

### Description of Issue Fix

The fix involves adding a synchronization check that detects when the
SearchView's SearchHandler doesn't match the current page's
SearchHandler. When a mismatch is detected, the code updates the
SearchView with the correct SearchHandler and refreshes the view. This
ensures search functionality always reflects the current page context
during navigation, preventing inconsistent behavior and UI elements.

Tested the behavior in the following platforms.
 
- [x] Windows
- [x] Mac
- [x] iOS
- [x] Android

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #8716

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

### Output

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="270" height="600"
src="https://github.com/user-attachments/assets/e7668e19-699e-49eb-a940-d160c1b5a10c">
| <video width="270" height="600"
src="https://github.com/user-attachments/assets/5d5a2d4c-6a5f-40f3-9630-12eb4af2045c">
|

---------
…g it to Null (#29487)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!
### Issue Details
 
In WinUI, setting the CollectionView's EmptyView to null does not fully
remove the associated visual element. While the reference is cleared,
the view remains in the visual tree and memory, leading to an
inconsistent UI state.
 
### Root Cause
 
When EmptyView was set to null, the handler exited early without
performing the necessary cleanup. As a result, the visual element
persisted in the UI tree and memory.
 
### Description of Change
 
The logic now explicitly collapses the EmptyView's visibility when
applicable and removes it from the logical tree to ensure it is detached
from the visual hierarchy. Internal references are cleared, and the
display flag is reset to maintain an accurate UI state.


#29463 -  Issue 1: EmptyView Template is Not Displayed 

### Root Cause 
The EmptyViewTemplate was not considered in the UpdateEmptyView, causing
it to be ignored.

### Description of Change
The EmptyViewTemplate is now properly managed to ensure it appears when
appropriate.

### Validated the behaviour in the following platforms
 
- [ ] Android
- [x] Windows
- [ ] iOS
- [ ] Mac
 
### Issues Fixed:
Fixes #18657 
Fixes #29463 
Fixes #18551
Fixes #23330 
 
### Screenshots
| Before  | After |
|---------|--------|
|  <video
src="https://github.com/user-attachments/assets/c11e8e9b-b173-4e7d-a504-8136ce250214">
|   <video
src="https://github.com/user-attachments/assets/0ba42b50-f490-4e66-a3d0-25e3e9b6f2b9"> 
|
…itching top tabs (#34735)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!


<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details

When navigating between top-level Shell tabs, the SearchHandler does not
update to match the currently selected page. Instead, the SearchHandler
from the previously selected tab remains visible and active, showing
outdated placeholder text, stale search results, and incorrect
interaction state.

This issue occurs specifically on iOS and MacCatalyst and is caused by a
regression introduced in a recent Shell lifecycle update. The page
lifecycle events (Appearing / Disappearing) no longer fire in the
correct order, preventing the toolbar from refreshing when a new
ShellContent becomes active. As a result, the SearchHandler associated
with the new page is never applied.

### Root Cause

The issue occurs on iOS and macCatalyst because a recent Shell lifecycle
update moved the _tracker.Page assignment to run before the navigation
animation completes. As a result, the old page’s Disappearing event was
unsubscribed prematurely, preventing it from firing. This
left _isVisiblePage stuck in the true state.

When the new page appeared, SetAppeared() exited early due to the
stale _isVisiblePage value, causing UpdateShellToMyPage() to never
execute. This disrupted the normal Shell page lifecycle and prevented
the toolbar from updating. As a result, the SearchHandler, TitleView,
and ToolbarItems from the previous tab remained visible instead of being
replaced with the new page’s toolbar state.

**Regression PR:** #33195

### Description of Change

The fix restores the correct lifecycle state by invoking
SetDisappeared() at the beginning of the if (oldPage != null) block in
OnPageSet. This call is additionally guarded with if (newPage != null)
to ensure it does not run during Dispose, where Page is set to null and
cleanup is handled separately.
 
When a tab switch assigns _tracker.Page before the animation completes,
the call to SetDisappeared() explicitly resets _isVisiblePage to false
and unsubscribes Toolbar.PropertyChanged for the outgoing page. After
that, the subsequent CheckAppeared() detects that Shell.CurrentPage ==
newPage and triggers SetAppeared(). With _isVisiblePage now correctly
reset, SetAppeared() runs its full logic: updating the SearchHandler,
TitleView, and ToolbarItems for the incoming page and re-subscribing to
Toolbar.PropertyChanged.
 
SetDisappeared() is already protected by if (!_isVisiblePage) return;,
so it becomes a no-op for normal lifecycle flows where the page already
disappeared correctly. No other navigation behavior is affected:
push/pop navigation creates a new tracker for each page (meaning oldPage
is always null), and app foreground/background cycles do not pass
through OnPageSet at all.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #34693

### Output  ScreenShot

|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/43966d7f-ff6f-45b0-be04-a540a03c00fe"
>| <video
src="https://github.com/user-attachments/assets/c6936dde-f766-40cf-a37b-24cc3b738486">|

---------
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description

This PR adds proper support for the IsSwipeEnabled property on
CarouselView2 for iOS. Currently, setting IsSwipeEnabled to false does
not disable user swipe gestures as expected. This behavior is
inconsistent and may lead to confusion or unintended navigation in
applications.

### Issues Fixed

Fixes #29391

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/3f0936b8-acb7-46b8-aa5c-db650ebc9f9d"
width="300px"/>|<video
src="https://github.com/user-attachments/assets/80c4ba3b-14be-4022-86d9-a36bb3080204"
width="300px"/>|

---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…opagated to children (#24275)

### Description of Change

An open ```SwipeView``` will close on tap, so a tap on an open
```SwipeView``` should be intercepted before it can be handled by child
views. Otherwise tapping to close an open swipeview will result in
```Button```s, ```TapGestureRecognisers``` etc within
```SwipeView.Content``` being activated.

### Issues Fixed

Fixes #23921

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…als.AI public APIs (#34574)

## Changes

- **eng/Versions.props**: Update
`MonoApiToolsMSBuildTasksPackageVersion` from `0.4.0` to `0.5.0`
- **Essentials.AI PublicAPI**: Move all `[MAUIAI0001]` API entries from
`PublicAPI.Unshipped.txt` to `PublicAPI.Shipped.txt` for net-ios,
net-maccatalyst, and net-macos — these APIs have now shipped

### Shipped APIs (per platform)
- `AppleIntelligenceChatClient` (constructors, `GetResponseAsync`,
`GetStreamingResponseAsync`)
- `NLEmbeddingGenerator` (constructors, `Dispose`, `GenerateAsync`)
- `NLEmbeddingExtensions.AsIEmbeddingGenerator`

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…undColor/TextColor (#34444)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
- Button with custom BackgroundColor and TextColor does not correctly
apply the Disabled VisualState defined in Styles.xaml when
IsEnabled=false.
- The issue occurs only when custom BackgroundColor and TextColor are
set on the Button. Removing these custom values allows the Disabled
VisualState to work correctly.

### Root Cause
PR #18103 introduced a specificity downgrade for implicit-style VSM
setters so that the `Normal` state cannot override locally-set values.
This downgrade was correctly applied to the `Normal` state but
inadvertently also prevented `Disabled`, `Focused`, and other non-Normal
states from overriding locally-set values.

### Description of Change
Added `WithFullVsmPriority()` to `SetterSpecificity` that promotes
implicit VSM back to full VSM priority. In
`VisualStateManager.GoToState`, this promotion is applied only when
transitioning to non-Normal states, preserving the original #18103
behavior for `Normal`.

### Validated the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Issues Fixed:
Fixes #34363 

### Screenshots
| Before  | After |
|---------|--------|
|  <video
src="https://github.com/user-attachments/assets/c28ea08b-d622-4aa0-a9ad-4bf4f2458cfb">
|   <video
src="https://github.com/user-attachments/assets/4561141f-add2-4e13-9235-ab8f03a3a2ac"> 
|

---------

Co-authored-by: Shane Neuville <5375137+PureWeen@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Root Cause:
When a `RadioButton` uses a `ControlTemplate` (i.e., `ControlTemplate !=
null`), `UpdateSemantics()` calls `ContentAsString()` to produce the
accessibility label. For simple string content, this works fine, but for
view-based content—such as a `Label` inside a
`VerticalStackLayout`—`ContentAsString()` ultimately falls back to
calling `ToString()` on the view object, returning a type name rather
than the user-visible text.

Additionally, the Android accessibility node for `RadioButton` was never
explicitly tagged as a radio button widget. Without the correct
`ClassName`, `Checkable`, and `Checked` node properties, TalkBack cannot
announce the checked/unchecked state of the control, even when a
semantic description is otherwise available.

### Description of Changes

**Enhancements to semantic description logic:**

- Added `GetSemanticDescriptionFromContent()` and
`TryGetSemanticDescription()` methods in `RadioButton.cs` to extract
semantic descriptions from nested content views, labels, and value
properties, improving accessibility for templated radio buttons.
- Updated `UpdateSemantics()` in `RadioButton.cs` to use the new
semantic extraction logic instead of the previous `ContentAsString()`
method.

**Platform-specific accessibility improvements:**

- Modified `SemanticExtensions.cs` for Android to set the correct class
name, checkable, and checked properties for radio buttons, ensuring
proper accessibility information is exposed.

**Testing and validation:**

- Added a new test
(`Issue34322_TemplatedRadioButtonUsesContentLabelForSemantics`) and
supporting helper methods in `RadioButtonTests.cs` to verify that
templated radio buttons use their content label for semantics,
addressing a specific accessibility issue.

### Issues Fixed

Fixes #34322

### Tested the behavior on the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

| Before Issue Fix | After Issue Fix |
|------------------|----------------|
| <img width="1180" height="984" alt="BeforeFixiOS"
src="https://github.com/user-attachments/assets/ca0afb3d-6b3a-422d-975f-772205e0c4cc"
/> | <img width="1225" height="986" alt="AfterFixiOS"
src="https://github.com/user-attachments/assets/b34f7c37-d512-48ef-99de-a721039465eb"
/> |

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

  ### Root Cause

`UpdatePlatformUnloadedLoadedWiring` in VisualElement.cs had this
early-exit guard:

  ```c#
 if (!_watchingPlatformLoaded && newWindow is null)
       return;
```

  This unconditionally skipped event wiring for any view without a MAUI Window. Native-hosted views (via ToPlatform()) never have a MAUI Window, so they were silently excluded.

  Additionally, HandlePlatformUnloadedLoaded had no case for native-hosted views — they fell through to the else detaching branch, which fired SendUnloaded immediately instead of wiring Loaded.

  ### Description of Change

  VisualElement.cs — Relax the guard using MauiContext as the discriminator:

   ```c# 
if (!_watchingPlatformLoaded && newWindow is null && Handler?.MauiContext is null)
     return;
```

VisualElement.Platform.cs — New else if branch for native-hosted views:

   ```c# 
if (Window is null && Handler?.MauiContext is not null &&
            Handler?.PlatformView is PlatformView nativeHostedView)
   {
       if (nativeHostedView.IsLoaded())
       {
           SendLoaded(false);
           _loadedUnloadedToken = this.OnUnloaded(SendUnloaded);
       }
       else
       {
           _loadedUnloadedToken = this.OnLoaded(SendLoaded);
       }
   }
   
```
> [!NOTE]
  > no SendUnloaded in the not-yet-loaded path — native-hosted views have no prior loaded state.

  What NOT to Do (for future agents)

   - ❌ Don't use Window is null alone — detaching views also have Window is null
   - ❌ Don't fire SendUnloaded for not-yet-loaded native-hosted views — no prior loaded state
   - ❌ Don't add _isNativeHosted flag — Handler?.MauiContext is not null is the canonical signal

  Issues Fixed

  Fixes #34310

  Platforms Tested

   - [X]  Android
   - [X]  iOS 
   - [X]  Windows 
   - [X]  MacCatalyst
…#34239)

### Root Cause
During Shell tab navigation animations, views move from off-screen into
their final positions (for example, `viewLeft < 0` during horizontal
movement or elevated viewTop values during vertical movement). The
existing logic applied `Math.Max(0, position - margin)` to account for
margins, which clamped negative or small positive values to zero. This
erased the signal used to detect that a view was still animating,
causing the safe area logic to treat animating views as already settled.
As a result, safe area padding was reduced too early during the final
animation frames, leading to visible padding jumps.
 
### Description of Change
To preserve correct animation detection, the animation state is now
calculated using raw view position values before any margin clamping is
applied, ensuring off-screen and in-transition states are not lost. The
safe area calculation logic was also reordered so animation checks are
evaluated before overlap checks for the left and right edges. This
prevents partial padding from being applied when a view is near its
final position but still animating. Finally, the animation flags were
renamed to `viewIsAnimatingHorizontally` and `viewIsAnimatingVertically`
for clarity.

### Note
The test case `SafeAreaShouldWorkOnAllShellTabs` already exists on the
main branch (`Issue33034.cs`). It was validated locally on an **API 36
emulator** to confirm the regression. Before the fix, the test failed
due to incorrect safe area padding during Shell tab animations. After
applying the fix, the test passes, confirming that safe area padding is
correctly maintained throughout the animation cycle.
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/5ddd040d-674f-4118-b393-8c83b544222e">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/67bb9044-002d-4b3a-a8cd-870d5d79d652">|

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details

- When DeviceDisplay.KeepScreenOn was set to true, it was not working
properly on Mac

### Root Cause of the issue

- UIApplication.SharedApplication.IdleTimerDisabled works only on iOS;
it does not work on Mac.

### Description of Change
**Mac Catalyst support for screen-on functionality:**

* Added platform-specific logic in `DeviceDisplayImplementation` to use
IOKit assertions for managing the "Keep Screen On" feature on Mac
Catalyst, instead of modifying `IdleTimerDisabled` as on iOS.
* Introduced the internal static `IOKit` class with P/Invoke wrappers
for `IOPMAssertionCreateWithName` and `IOPMAssertionRelease`, enabling
assertion management for display sleep prevention on Mac Catalyst.

**Dependency and import updates:**

* Added `System.Runtime.InteropServices` and `CoreFoundation` imports to
support native interop required for IOKit assertion management.
<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #26059

### Tested the behaviour in the following platforms

- [x] - Windows 
- [ ] - Android
- [ ] - iOS
- [x] - Mac

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Root Cause:
ComboBox MinWidth wasn’t reset when the dropdown closed, which prevented
it from resizing correctly.
### Description of Change
Updated `OnMauiComboBoxDropDownClosed` in `PickerHandler.Windows.cs` to
reset the ComboBox.MinWidth to 0 when the dropdown closes, allowing the
picker to resize with its parent.

Already, ComboBox.MinWidth is set in two other places:
- When
[opening](https://github.com/SubhikshaSf4851/maui/blob/fa21fd3ce071e2b76ceb95a2d029968647ea7912/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs#L135)
the ComboBox, where ComboBox.ActualWidth is assigned to
ComboBox.MinWidth. So, the ComboBox.MinWidth will always be set every
time the ComboBox is opened.
- After
[selecting](https://github.com/SubhikshaSf4851/maui/blob/fa21fd3ce071e2b76ceb95a2d029968647ea7912/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs#L125)
an item, where 0 is already assigned to ComboBox.MinWidth, similar to
our fix, and this also triggers the ComboBox’s closed event.
<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #32984 
### Tested the behavior in the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

### Screenshot

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/a920efa8-85f2-4f6f-ba1b-7f2bb448a1d9">
| <video
src="https://github.com/user-attachments/assets/88e7e898-d13d-4c89-b7dd-e6536336e5f6">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
…3917)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

Fixes #33773

When a MAUI Blazor Hybrid app references a Razor Class Library (RCL),
the RCL's precompressed static web assets (`.gz`, `.br`) were
incorrectly included in the Android APK, bloating the app bundle. These
compressed files are unnecessary since Blazor Hybrid serves assets
locally, not over HTTP.

## Root Cause

RCLs build independently with `CompressionEnabled=true` (SDK default),
producing compressed asset alternatives. The consuming MAUI project's
`CompressionEnabled=false` setting (from the WebView package) comes too
late to affect already-built RCL assets. The
`ConvertStaticWebAssetsToMauiAssets` target was including ALL static web
assets without filtering.

## Solution

Add a condition to the `ConvertStaticWebAssetsToMauiAssets` target that
filters out compressed alternatives when `CompressionEnabled=false`. The
fix uses `AssetRole` metadata to distinguish:
- **Primary** assets (user files like `test.js` or `archive.tar.gz`) →
Preserved
- **Alternative** assets (SDK-generated compressed variants like
`test.js.gz`) → Filtered when compression disabled

This ensures legitimate user files with `.gz` or `.br` extensions are
not incorrectly filtered.

## Test Results

| Scenario | Before Fix | After Fix |
|----------|------------|-----------|
| Simple MAUI Blazor | 0 compressed | 0 compressed ✅ |
| MAUI + RCL | 8 compressed | **0 compressed** ✅ |
| MAUI + Shared RCL | 8 compressed | **0 compressed** ✅ |
| Blazor Web + RCL | Has compression | Has compression ✅ |
| User archive.tar.gz | N/A | **Preserved** ✅ |

## Changes

1. **Fix**: `Microsoft.AspNetCore.Components.WebView.Maui.targets` -
Filter compressed alternatives
2. **Test**: `BlazorTemplateTest.cs` - Integration test verifying no
`.gz`/`.br` in APK

## Testing

An integration test was added that:
1. Creates a `maui-blazor-web` template (MAUI app + shared RCL + Web
app)
2. Adds a test JS file to the shared RCL
3. Publishes the MAUI app for Android
4. Extracts the APK and verifies NO `.gz`/`.br` files exist
5. Verifies original assets ARE present (uncompressed)
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details

- When setting the FlowDirection property on a DatePicker control, the
control remains left-to-right (LTR) on iOS, regardless of the specified
FlowDirection.

### Root Cause

- The iOS MapFlowDirection used a concrete type (DatePickerHandler)
instead of the expected interface (IDatePickerHandler), causing the
system to skip the platform-specific implementation and fall back to the
generic ViewHandler.MapFlowDirection, which lacked the necessary text
alignment logic for iOS.

### Description of Change

- Corrected the MapFlowDirection method signature to align with the
handler mapping system's interface contract.
- Added logic to update text alignment in DatePickerExtensions.cs based
on the EffectiveFlowDirection property, ensuring proper alignment for
RightToLeft and LeftToRight flow directions.
- Documented the updated API signature and method changes for accurate
public API tracking.

### Issues Fixed
Fixes #30065 

### Validated the behaviour in the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/62a7ff2e-d7bb-42e5-bcc4-5eaed57fc671">
| <video
src="https://github.com/user-attachments/assets/2290dabe-26d5-4e3a-b809-2e27aa03d59d">
|

---------

Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…ectionView (#32775)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details:
On iOS, the FlowDirection is not applied to Header and Footer in a
CollectionView when they are used along with an EmptyView and no
ItemTemplate or ItemsSource is defined.


### Root Cause
**Header/Footer as String:**
FlowDirection was not handled inside StructuredItemsViewController, so
the text-based Header/Footer did not update.
**Header/Footer as View:**

- The initial FlowDirection is applied correctly when the view is added
as a logical child in TemplatedCell2.BindVirtualView().
- For runtime changes, the property propagation did not update the
Header/Footer flows direction properly.
- Additionally, the existing update logic in
ItemsViewController2.UpdateFlowDirection() relied on the presence of
ItemsView.ItemTemplate. When Header/Footer was used without an
ItemTemplate—such as when used together with EmptyView, ItemTemplate was
null. This caused the FlowDirection update for Header/Footer views to be
skipped.

### Description of Change

- Updated StructuredItemsViewController to explicitly handle
FlowDirection for Header/Footer when ItemTemplate is not defined. This
ensures correct behavior in EmptyView scenarios.
- When ItemTemplate is present, FlowDirection updates continue to be
handled by ItemsViewController, avoiding duplicate updates. Also ensured
FlowDirection is applied to all visible supplementary views (both
DefaultCell2 and TemplatedCell2) to support runtime changes.

### Validated the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Issues Fixed:
Fixes #32771 

### Screenshots
| Before  | After |
|---------|--------|
|  <video
src="https://github.com/user-attachments/assets/6c6aab13-6273-4583-abfc-d6e4ee3328ed">
|   <video
src="https://github.com/user-attachments/assets/a363a76b-c4e6-4478-b00a-b07ee9d27b4d"> 
|

---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
… Text property of Entry. (#30242)

### Issue Details:

Exception thrown when give more than 5000 characters to the Text
property of Entry on Android platform.
        
### Root Cause:

When the Entry contains more than 5000 characters and the IsPassword
property is mapped before the MaxLength property, the EditText input
type is set to InputTypes.ClassText | InputTypes.TextVariationNormal.
After the input type is updated, we attempts to restore the previous
cursor position, which exceeds 5000 characters. This results in an
IndexOutOfBoundsException during the selection process.

### Description of Change:

To prevent the crash, I reordered the property mappers by applying the
MaxLength mapper before the IsPassword mapper in EntryHandler

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A


### Issues Fixed:

Fixes #30144  

### Screenshots
| Before  | After  |
|---------|--------|
| The application is crashed | <Image
src="https://github.com/user-attachments/assets/f690b53b-a2f2-4adb-89b4-e190b94179b9">
|
…4228)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

Fixes #34104

Custom platform backends (e.g., Linux/GTK) currently have no supported
way to implement `DisplayAlert()`, `DisplayActionSheet()`, or
`DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`,
`IAlertManagerSubscription`) is internal, forcing custom backends to use
`DispatchProxy` + heavy reflection to intercept dialog requests.

This PR introduces two public interfaces to enable custom platform
backends to implement alert dialogs without reflection:

### New Public APIs

**`IAlertManager`** — Public interface for the full alert management
lifecycle. Custom backends can implement this to completely replace the
default `AlertManager`:

```csharp
public interface IAlertManager
{
    void Subscribe();
    void Unsubscribe();
    void RequestAlert(Page page, AlertArguments arguments);
    void RequestActionSheet(Page page, ActionSheetArguments arguments);
    void RequestPrompt(Page page, PromptArguments arguments);
}
```

**`IAlertManagerSubscription`** — Public interface for platform-specific
dialog implementations. The default `AlertManager` already resolves this
from DI, so custom backends can register their implementation directly:

```csharp
public interface IAlertManagerSubscription
{
    void OnAlertRequested(Page sender, AlertArguments arguments);
    void OnActionSheetRequested(Page sender, ActionSheetArguments arguments);
    void OnPromptRequested(Page sender, PromptArguments arguments);
}
```

### Usage

Two levels of customization are now available:

```csharp
// Simple: Just provide custom dialog implementations
builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>();

// Advanced: Replace the entire alert management system
builder.Services.AddSingleton<IAlertManager, CustomAlertManager>();
```

### Changes

- **New:** `IAlertManager` public interface in
`Microsoft.Maui.Controls.Platform`
- **New:** `IAlertManagerSubscription` public interface (moved from
internal nested interface)
- **Modified:** `AlertManager` now implements `IAlertManager`
- **Modified:** `Window.AlertManager` property typed as `IAlertManager`,
resolves custom implementation from DI
- **Modified:** Tests updated + 2 new tests for DI resolution
- **Updated:** All `PublicAPI.Unshipped.txt` files

### Related

- Related PR: #33267 (draft, creates internal `IAlertManager` for
#33266)
- Real-world use case: [Maui.Gtk
GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs)
— 370 lines of reflection that this PR eliminates

---------
…ning from minimized state (#34779)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Root cause
When the app resumes from a minimized state, the `CollectionView` on
MainPage re-evaluates its bindings. The `SelectionChangedCommand` fires
with a `null` `SelectedProject`, calling NavigateToProject(null), which
returns `null`. The `AsyncRelayCommand` generated by RelayCommand tries
to await/check this null Task internally in `AwaitAndThrowIfFailed`,
causing the `NullReferenceException`.

### Description of Change

<!-- Enter description of the fix in this section -->
This pull request makes a minor improvement to the `NavigateToProject`
command in the `MainPageModel` to ensure it always returns a `Task`,
even when the input is null. This helps maintain consistency and
prevents potential issues with null returns.

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #34720

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
dependabot Bot and others added 20 commits June 23, 2026 09:10
Updated [Magick.NET-Q8-AnyCPU](https://github.com/dlemstra/Magick.NET)
from 14.12.0 to 14.13.1.

<details>
<summary>Release notes</summary>

_Sourced from [Magick.NET-Q8-AnyCPU's
releases](https://github.com/dlemstra/Magick.NET/releases)._

## 14.13.1

### What's Changed
- Fixed loading of animated AVIF image as MagickImageCollection (#​2000)
- Fixed determining the number of frames when reading animated AVIF
images (#​2005)
- Fixed loaded of indexed color PSD file (#​2007)
- Another fix when reading JPEG compressed TIFF files. (#​2016)

### Related changes in ImageMagick since the last release of Magick.NET:
- Stack overflow in fx operation
(GHSA-rcr6-g7jc-f57g)
- Heap Buffer Over-Write of a single byte in the JP2 encoder
(GHSA-533m-3wf6-c33v)
- Use-After-Free in MSL decoder
(GHSA-5r4x-w6p5-222q)
- Infinite Loop in the MIFF decoder can lead to CPU exhaustion
(GHSA-7gg8-qqx7-92g5)
- Heap Buffer Over-Write in IPL decoder when reading multiple images of
different dimensions
(GHSA-36wm-hprc-mcf5)
- Heap Buffer Over-Write in MIFF encoder when using LZMA compression
(GHSA-jcqp-6r6f-3mfx)

### Library updates:
- ImageMagick 7.1.2-23 (2026-05-17)
- aom 3.14.0 (2026-05-12)
- openexr 3.4.11 (2026-04-30)
- libhwy 1.4.0 (2026-04-23)
- lcms 2.19.1 (2026-05-06)
- openjph 0.27.3 (2026-05-14)

**Full Changelog**:
dlemstra/Magick.NET@14.13.0...14.13.1

## 14.13.0

### What's Changed
- Added `PixelDifferenceCount` to `ErrorMetric`.

### Related changes in ImageMagick since the last release of Magick.NET:
- Corrected the patch that was made earlier to fix reading JPEG
compressed TIFF images (#​1993)
- Call CloseBlob on the correct image to prevent the blob from remaining
open (#​1997)

### Library updates:
- ImageMagick 7.1.2-21 (2026-04-21)
- harfbuzz 14.2.0 (2026-04-20)
- libpng 1.6.58 (2026-04-15)
- libraqm 0.10.5 (2026-04-11)
- libraw 0.22.1 (2026-04-06)
- libxml2 2.15.3 (2026-04-15)
- openexr 3.4.9 (2026-04-17)
- openjph 0.27.0 (2026-04-14)

**Full Changelog**:
dlemstra/Magick.NET@14.12.0...14.13.0

Commits viewable in [compare
view](dlemstra/Magick.NET@14.12.0...14.13.1).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Magick.NET-Q8-AnyCPU&package-manager=nuget&previous-version=14.12.0&new-version=14.13.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/dotnet/maui/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#35927)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## What this PR adds

Two new agentic workflows that walk open CI-failure tracking issues
filed by the existing scanners and open draft `[ci-fix]` PRs against the
matching branch:

- `.github/workflows/ci-status-fix.md` — processes `[ci-scan]` issues,
opens PRs against **`main`**.
- `.github/workflows/ci-status-fix-net11.md` — processes
`[ci-scan-net11]` issues, opens PRs against **`net11.0`**.

They are the natural counterpart to the existing `ci-status-main.md` /
`ci-status-net11.md` detection workflows: one pair identifies, the other
proposes a fix. **No KBE / Build Analysis integration** — just identify
→ auto-fix PR, as requested.

Also includes two small, surgical prompt edits to both scanner files so
the fixers can trust what they emit.

## Why two workflows instead of one

The fixer logic is identical for both branches; the split is forced by a
gh-aw transport constraint, not by behavior.

gh-aw always generates a "transport patch" for its `create-pull-request`
safe-output **relative to a single static `base-branch`**, and
`max-patch-size` is hard-capped at **10 MB** by the gh-aw schema
(raising it past 10 MB is a compile error). The `main` ↔ `net11.0`
divergence is ~22 MB / ~1,000 files, so a one-file `net11.0` fix built
against a `main` base produces a ~22 MB transport patch and is
unconditionally rejected (file-count guard, then size).

Because `base-branch` is one static value per workflow, each base needs
its own workflow. With `base-branch: net11.0`, gh-aw builds the
transport patch relative to `net11.0`, so the patch is just the fix's
own delta. This was validated live (see below): the net11.0 fixer opened
a clean **1-file** draft PR against `net11.0`.

## Design highlights

**Each workflow is hard-pinned to exactly one base branch, enforced at
three layers.**

1. **gh-aw declarative gate**:
`safe-outputs.create-pull-request.base-branch` pins the base (`main` /
`net11.0`), and `allowed-base-branches` (`[main]` / `[net11.0]`) makes
gh-aw reject any other base.
2. **Prompt rule**: the agent only processes the matching label
(`ci-scan` / `ci-scan-net11`) and checks out `origin/<branch>` (Step
5.2) before authoring, so the transport patch and the downstream push
are both exactly the one-file fix delta.
3. **Self-check before emission**: the agent greps its own PR body for
`Target branch: <branch>` and confirms `base` matches; mismatch aborts.

**Iterative, capped at 5 attempts per tracking issue.** Attempt count
comes from a live GitHub PR search for `"Refs: dotnet/maui#<N>"` in
closed-unmerged `[ci-fix]` PRs (GitHub is the durable store — no per-run
state needed). After the 5th closed-unmerged attempt the workflow stops
and defers to humans (the open tracking issue is the hand-off surface).
A dedicated `[ci-fix][needs-human]` hand-off PR is planned but
**currently deferred** (Step 6 records a skip and emits no PR). Each
attempt reads prior closed PRs' approaches and close comments and must
propose a substantively different approach.

**"Is it actually fixed?" check.** Before any fix attempt, the agent
fetches the latest completed build of the failing pipeline on the target
branch and `grep -F`s the issue's failure signature against the leaf-log
output. Zero hits → silently skips ("appears fixed in latest build").
Tracking issue closure stays a human decision.

**De-flake capability for intermittent test failures.** A flakiness
probe classifies a reproducing failure as (a) infra → skip, (b)
test-quality → de-flake PR, or (c) product-masking → product fix /
hand-off. A de-flake replaces sleeps/races with condition waits and
tightened assertions; it **never** adds `[Ignore]` / `[Retry]`, weakens
assertions, or bumps timeouts.

**Visual-regression filter is the first gate.** Silently skips any issue
whose title, body, error message, or failed task names match
`screenshot` / `snapshot` / `visual diff` / `baseline image` /
`VerifyScreenshot` / etc. gh-aw can't judge visual diffs and must never
modify baseline images.

**Never mutes a test.** Stages with `[ActiveIssue]`, `Skip = "..."`,
`[SkipOnPlatform]`, csproj `<*Incompatible>` / `<ExcludeFromTestRun>`,
or edits to baseline images under `TestAssets` / `Snapshots` /
`Baselines` are detected and rejected. If the only candidate fix is a
mute, the run records a skip and stops.

**MAUI area bounds.** Compile / XAML breaks are in bounds (≤ 20 lines,
single file when possible). Device-test and UI-test failures (past the
visual-regression gate) become `help`-only PRs or de-flakes. Handler
lifecycle, threading, safe-area, perf hot-paths, Gradle/Maven feed, and
infra failures are skipped — too risky for an autonomous fix.

**Outputs only via `safe-outputs`.** Tracking issues are locked so no
comments are possible. `draft: true`, `max: 3` PRs per run,
`environment: gh-aw-agents` gating on the write-capable job,
`allowed-files` restricts to `src/Core/**`, `src/Controls/**`,
`src/Essentials/**`, `src/BlazorWebView/**`, `src/TestUtils/**`,
`src/Templates/**`, `**/PublicAPI.Unshipped.txt` (which already excludes
`.github/**`).

## Validated live

The net11.0 workflow was run end-to-end against a real `[ci-scan-net11]`
issue (#35981, a flaky `DropEventCoordinates` iOS 18.5 drag-and-drop
test). It opened draft PR **#36027** targeting `net11.0` with a clean
**1-file** de-flake (reset-between-retries + a tightened
positive-coordinate assertion; no banned mute/retry patterns) and
correct body markers (`Refs`, `Target branch: net11.0`, `Attempt 1/5`,
`Flake class: test-quality`). #36027 is left open as a genuine candidate
fix for maintainers to review — it proves the `base-branch: net11.0`
split produces a small, in-cap transport patch.

## Two small scanner edits (so the fixers can rely on what they emit)

Both `ci-status-main.md` and `ci-status-net11.md`:

1. **Mandatory `Build ID: <integer>` line** in the issue body template.
The fixer requires it as a field gate (skipping any issue missing it)
and cites it as the *original failing build* in its PR audit trail; the
existing `Build: <URL>` line is opaque to grep. (The reproduce-check
itself re-fetches the *latest* build of the pipeline.)
2. **Match-count gate** requiring the scanner to verify its own primary
error substring actually appears in the fetched failure log before
filing, and embed the result as a second hidden marker:
   ```
   <!-- ci-scan-match-count: N hits in failure.log -->
   ```
Issues with 0 matches are not filed. This blocks hallucinated signatures
from ever entering the fixers' work lists. The substring is treated as
untrusted data — it is written to a pattern file via a fresh per-run
random-delimiter single-quoted heredoc and matched with `grep -F -f`
(never interpolated into a shell command), mirroring the injection-proof
pattern the fixers use.

## Lifecycle and stop conditions

| State | Action |
|---|---|
| Open `[ci-fix]` PR already exists for the issue | Skip — human owns
the PR |
| Merged `[ci-fix]` PR exists | Skip — fix already landed |
| Open human PR (non-`agentic-workflows` label) references the issue |
Skip — human is on it |
| `attempt_count < 5` and signature still reproduces | Open attempt N+1
|
| `attempt_count >= 5` | Stop and defer to humans; never retry
(dedicated `[ci-fix][needs-human]` PR deferred — see Step 6) |
| `attempt_count` search inconclusive (API error / `incomplete_results`)
| Skip — cannot safely confirm the cap |
| Latest build no longer reproduces the signature | Skip — "appears
fixed" |
| Issue body missing required fields (`Build ID`, fingerprint, error
block) | Skip — scanner needs prompt update |
| Only candidate fix is a mute | Skip |
| Only candidate fix modifies visual baselines | Skip |
| No novel approach producible vs prior attempts | Skip — defer to next
tick |

## Files

- **NEW**: `.github/workflows/ci-status-fix.md` — main-branch fixer
(`base-branch: main`)
- **NEW**: `.github/workflows/ci-status-fix.lock.yml` — generated by `gh
aw compile`
- **NEW**: `.github/workflows/ci-status-fix-net11.md` — net11.0-branch
fixer (`base-branch: net11.0`)
- **NEW**: `.github/workflows/ci-status-fix-net11.lock.yml` — generated
by `gh aw compile`
- **EDIT**: `.github/workflows/ci-status-main.md` — `Build ID` line +
match-count gate
- **EDIT**: `.github/workflows/ci-status-net11.md` — `Build ID` line +
match-count gate

`gh aw compile` passes cleanly on both new workflows (0 errors, 0
warnings).

## Things this PR explicitly does NOT do

- Does **not** integrate Build Analysis / KBE in any form.
- Does **not** add a feedback / KPI workflow (could be a follow-up if
maintainers want one — the marker blocks in PR bodies are designed to
make it easy).
- Does **not** read PR review comments as instructions — the integrity
gate filters them and the agent never treats them as authoring input.
- Does **not** close tracking issues — closure stays a human decision.
- Does **not** modify any production source code in this PR;
workflow-only change.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…s trackers (#36066)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Summary

Each `[Release Readiness]` tracker now opens with a **nightly dogfood
feed freshness banner** for that release's lane, so a release captain
can tell at a glance whether dogfooders are validating *current* bits or
testing stale builds. A fresh nightly is expected daily; when one stops
appearing, the tracker should say so loudly.

This is internal release-readiness tooling
(`.github/skills/release-readiness/`) — no product/runtime code changes.

### What it looks like

- ✅ fresh (`< 3` days): `**Nightly dogfood feed:** ✅ \`dotnet11\` (net11
preview) — latest \`11.0.0-preview.6.26322.3\` built today.`
- ⚠️ aging (`3–6` days): blockquote with age + publish date.
- ❌ stale (`≥ 7` days): blockquote alarm — e.g. (live, SR8 band today):
`❌ Nightly dogfood feed is STALE — 11 days … Latest build
\`10.0.80-ci.main.26310.5\` published 2026-06-11 … builds appear to have
stopped`.
- Muted one-liners for *unknown* (feed query failed) and *no matching
build* (band naming changed) — never a false alarm.

### How it works

- **New shared helper `scripts/NightlyFeed.ps1`** (single source,
dot-sourced by both engines + the test harness):
- `Get-NightlyFeedFreshness` — queries the lane's Azure Artifacts feed
(`dotnet10`, `dotnet11`, …) and returns the newest build whose version
matches a **band prefix**, selected by `catalogEntry.published`. The
feed orders versions by *version number, not date*, and mixes build
families on one feed, so freshness **must** come from publish timestamps
scoped by a version band. The network call is **fail-open** (any error →
`$null`) and takes an injectable `-Fetcher` so it's fully unit-tested
offline.
- `Format-NightlyFeedBanner` — **pure, deterministic** renderer (caller
passes `-Now`); tiers fresh/aging/stale + muted unknown/no-match.
Thresholds are parameters (default 3/7 days).
- **SR engine** (`Get-ReleaseReadiness.ps1`): on full (`all`) runs, maps
the SR lane to `dotnet<Major>` + the `<Major>.0.<Patch>` band —
in-flight SR → the SR branch's band; candidate → main's band — queries
freshness, and renders the banner under the **Generated** line.
Band-**number** matching is deliberate: it's resilient to family-keyword
churn (an SR8 `.80` build is tagged `ci.main`, *not* `ci.inflight`, so a
keyword match would miss it).
- **Preview engine** (`Get-PreviewReadiness.ps1`): maps the preview to
`dotnet<Major>` + the `<Major>.0.0-preview.<N>` band (iteration read
from `Versions.props` at the survey ref), renders the banner under
**Overall status**.
- **Defensive load**: both engines dot-source the helper guarded by
`Test-Path` + `Get-Command`; a missing/unloadable helper degrades to *no
banner* rather than crashing the unattended nightly tracker job. The
freshness query is wrapped in try/catch and gated to non-test code
paths, so existing E2E tests stay network-free.

### Testing

- **26 new offline assertions** for the helper: banner tiers, `unknown`
/ `matched=$false`, future-publish clamp, custom thresholds,
deterministic publish date; and `Get-NightlyFeedFreshness` with a mocked
`-Fetcher` covering newest-by-date (not version) selection, band-prefix
filtering, fail-open on throw, and paged-registration `@id` follow-up.
Plus SR render-path wiring assertions (banner appears after
**Generated**; absent when the key isn't set).
- **Offline suite: 592/0.**
- **Live validation** against the real feeds (2026-06-22): `dotnet10
^10.0.90-` → fresh today; `dotnet10 ^10.0.80-` → STALE 11d; `dotnet11
^11.0.0-preview.` → fresh today.
- Full suite is 602 passed / **2 pre-existing env-specific failures** in
the *unmodified* `Find-ReleaseReadinessTrackers.ps1` E2E (its git-root
guard fail-closes when run from a `/tmp` worktree without `-Repo`);
identical on baseline, unrelated to this change.

### Follow-ups (out of scope)

- The companion `Nightly-Builds` wiki page is stale (mislabels which
branch feeds `dotnet9`/`dotnet10`, missing `dotnet11`); a corrected
draft is being reviewed separately.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description

Updates `eng/scripts/get-maui-pr.sh` and `eng/scripts/get-maui-pr.ps1`
so users can still apply PR package artifacts when the aggregate
`maui-pr` build is red because of unrelated CI legs, as long as the
package-producing artifacts exist for the current PR commit.

### Changes

- Treat a red aggregate `maui-pr` build as a warning instead of an
immediate abort.
- Keep `PackageArtifacts` as the hard gate before downloading/applying
packages.
- Filter AzDO fallback builds to the current PR head/merge context using
`triggerInfo.pr.sourceSha`, `sourceVersion`, and the PR merge SHA.
- Warn when `Pack macOS` or `Pack Windows` timeline records do not
report success.
- Update troubleshooting text to refer to completed `maui-pr` builds
with `PackageArtifacts` rather than green checks.

### Validation

- `bash -n eng/scripts/get-maui-pr.sh`
- PowerShell parser validation for `eng/scripts/get-maui-pr.ps1`
- `git diff --check`
- Local throwaway MAUI projects under
`/Volumes/NieuwVolume/maui-pr-artifact-verification-20260616101523`:
- PR `#35805`: red aggregate build `1461390`, `PackageArtifacts`
present, pack jobs succeeded; Bash and PowerShell scripts applied
package `10.0.80-ci.pr35805.26312.37`; `dotnet restore` succeeded.
- PR `#35923`: green aggregate build path applied package
`10.0.80-ci.pr35923.26315.57`; `dotnet restore` succeeded.
- PR `#35626`: missing `PackageArtifacts` failed before mutating the
project.
  - PR `#999999`: nonexistent PR failed cleanly during PR lookup.
- Wrong-SHA harness for PR `#35805`: refused to use older completed
builds when none matched the requested head/merge commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… VS Live Property Explorer (#36063)

### Issue details:
After PR #33584 (BindableObject property access micro-optimizations),
Visual Studio's Live Property Explorer stops showing any property values
for MAUI controls. The feature becomes completely blank.
 
### Description of changes:
PR #33584 removed GetLocalValueEnumerator(), LocalValueEnumerator, and
LocalValueEntry from BindableObject as "unused dead code" — a grep of
the MAUI codebase confirmed zero internal callers. However, Visual
Studio's Live Property Explorer calls GetLocalValueEnumerator() via
reflection at runtime to enumerate locally-set bindable property values
on live objects. With these types removed, the reflection call fails
silently and the panel shows nothing.
 
This changes restores all three types, adapted to the new
Dictionary<int, BindablePropertyContext> storage introduced by #33584 —
the enumerator now iterates .Values (the BindablePropertyContext objects
directly) and reads context.Property to expose the BindableProperty,
since the dictionary key is now an int rather than the property itself.

**Tested the behavior in the following platforms.**
- [ ] Android
- [x] Windows
- [ ] iOS
- [ ] Mac

| Before  | After  |
|---------|--------|
| **Windows**<br> <video
src="https://github.com/user-attachments/assets/df3a3448-c79c-4457-8901-f2a075087df4"
width="300" height="600"> | **Windows**<br> <video
src="https://github.com/user-attachments/assets/2dcbdb35-2336-44bd-9c8b-baf1f9b64b4a"
width="300" height="600"> |

---------

Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

Adds a guide for Microsoft maintainers and community contributors
explaining the automated PR review workflow:

- `/review`
- `/review <platform>`
- `/review rerun`
- `/review tests`

The guide also explains the `maui-copilot` pipeline flow, AI Summary and
Test Failure Review comments, local `/review tests` usage,
troubleshooting, and related implementation files.

### Companion review-output changes

Beyond the documentation, this PR also refines the review-comment output
to keep it consistent with the guide and with the project's
review-symbol conventions:

- **`Find-RegressionRisks.ps1`** — distinct colorless severity glyphs in
the regression markdown (`✗` REVERT / `⚠` OVERLAP / `●` CLEAN).
- **`post-ai-summary-comment.ps1`** — `Test-PhaseContentIsNoOp`
recognizes the `●` (and legacy `🟢`) regression no-op markers so empty
sections stay suppressed; **Next Steps** renders below **Review
Sessions**.
- **`post-inline-review.ps1`** — inline-comment marker uses a generic
`(multi-model)` label instead of a hardcoded model roster.
- **`pr-preflight.md`** — review-symbol set aligned (`✗`/`⚠`/`ℹ`).

Producer/consumer pairs (e.g. the regression no-op markers) are kept in
lock-step and covered by `Post-AISummaryComment.Tests.ps1`.

### Issues Fixed

No issue filed.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: kubaflo <kubaflo@users.noreply.github.com>
…plementing AzDO (#36080)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Problem

The `/review rerun` scanner (`rerun-review-scanner`) dispatched **zero**
AzDO reviews after #35955, and the few it should dispatch would target
the wrong branch. Two independent bugs:

### Bug 1 — every dispatch aborted with a spurious 404

In the **gh-aw safe-output job**, the `gh` CLI returns `HTTP 404` for
`repos/dotnet/maui/pulls/N` — even with `pull-requests: write` on a
public repo. #35955 misread these as transient and "hardened" the
not-found guard, so it now faithfully *confirms* the bogus 404 and skips
every PR. Evidence it is not a permission/token problem: the
`pre_activation` job (only `Metadata: read`) reads the same PRs fine,
and the built-in `safe_outputs` job (octokit) succeeds in the same run.

### Bug 2 — custom review branches silently downgraded to `main`

The candidate builder decided whose `/review -b <branch> -p <platform>`
to trust using the comment's `author_association`. Under the Actions
`GITHUB_TOKEN`, a maintainer whose org membership is private reads as
`CONTRIBUTOR` (not `MEMBER`), so their command was dropped and the rerun
fell back to the `main` pipeline. A live scan confirmed it dispatched
four net11 (`feature/enhanced-reviewer`) PRs on `main`.

## Fix — do exactly what a maintainer `/review` does

**Bug 1:** instead of re-implementing PR validation + OIDC + the AzDO
trigger inside the safe job, the scanner now **dispatches the same
`review-trigger.yml` workflow `/review` runs**, via `workflow_dispatch`.
That workflow owns PR validation, the `s/agent-review-in-progress` lock,
platform inference, OIDC, and the AzDO trigger. (`workflow_dispatch` via
`GITHUB_TOKEN` always creates a run — it is exempt from Actions
recursion-prevention.)

- `Invoke-RerunReviewTrigger.ps1` is now pure: validate batched
`decisions` against `candidates.json`, emit `actions.json`. No
`gh`/AzDO/OIDC/lock/rate-limit I/O.
- A `github-script` (octokit) step performs all GitHub writes — octokit
works in the safe-job context where the `gh` CLI does not. `trigger` →
`createWorkflowDispatch(review-trigger.yml,{pr_number,platform,pipeline_ref})`
+ 👍; `skip` → 👎 + remove the queue label.
- Permissions: `+actions:write`, `−id-token:write`; dropped the
`AZDO_TRIGGER_*` secrets from the job.

**Bug 2:** authorize `/review` options by a **live
collaborator-permission lookup** (`collaborators/<user>/permission` →
write/maintain/admin) — the exact call `review-trigger.yml`'s auth step
makes. It only needs `metadata: read` (every token has it) and reflects
current access. **No new secret or permission.**

- `Resolve-RerunEligibility.ps1`: add `Test-ReviewOptionLoginTrusted`
(cached per login); `Get-LatestReviewCommandOptions` computes trust
through it. Removed the `author_association` gate.
- `Query-RerunReadyPRs.ps1`: drop the `author_association` helpers; pass
`-Owner/-Repo`.

## Validation

- **69 Pester tests pass** (36 dispatch + 33 resolver), incl. a
regression test that an `author_association=NONE` command is still
honored when the login has write access.
- **Live, real (non-dry) scan**: the safe job validated all decisions
with **no 404s** and octokit performed real `createWorkflowDispatch`,
producing two `review-trigger.yml` runs that triggered real AzDO
`maui-copilot` builds (HTTP 200, Run IDs 14459427 & 14459428).
- **Real-data check for Bug 2**: PR #34564's history now resolves to
`pipelineRef=feature/enhanced-reviewer` (author `kubaflo`,
`author_association=CONTRIBUTOR`) instead of `main`, using the live
permission lookup.

## Files

- `.github/scripts/Invoke-RerunReviewTrigger.ps1`,
`.github/scripts/Invoke-RerunReviewTrigger.Tests.ps1`
- `.github/scripts/Resolve-RerunEligibility.ps1`,
`.github/scripts/Resolve-RerunEligibility.Tests.ps1`
- `.github/scripts/Query-RerunReadyPRs.ps1`
- `.github/workflows/rerun-review-scanner.md` + recompiled `.lock.yml`
- `.github/docs/agent-labels.md`

---
🔍 _This PR was created by an AI agent (GitHub Copilot CLI) on behalf of
@kubaflo._

---------

Co-authored-by: kubaflo <kubaflo@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ts doc (#36067)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Summary

This is a **tooling/agent-infrastructure change only** (everything is
under `.github/` plus the local `/review tests` runner) — no product
source or public API changes.

It converges the automated `/review tests` workflow (the
`review-test-failures` skill) with the interactive
`azdo-build-investigator` skill so that **both deliver the same end
result** — a CI **merge-readiness verdict** plus a **base-branch
baseline failure review** — while removing the duplicated MAUI CI
knowledge that was copy-pasted across several files and at real risk of
drifting.

The two skills can't share *tooling* (the `ci-analysis` plugin that
powers `azdo-build-investigator` is a stdio MCP server, which the gh-aw
runtime can't run), so "minimal duplication" is achieved by sharing
**docs**, not tools.

## Architecture: "shared knowledge, two roles"

One canonical facts doc; every consumer references it instead of
re-stating the facts.

- **New `.github/docs/maui-ci-facts.md`** — single source of truth for
pipeline names/IDs (`maui-pr` 302, `maui-pr-devicetests` 314,
`maui-pr-uitests` 313), AzDO data sources, the XHarness exit-0 blind
spot, test-count deduplication, the **baseline-comparison rule**,
visual-baseline/platform-mismatch guidance, Gradle/CFSClean signatures,
the common-failure-pattern table, and the **merge-readiness criteria**.
Its header lists every consumer, kept bidirectionally accurate.

## What changed

| Area | Change |
| --- | --- |
| `review-test-failures/SKILL.md` | References the facts doc; adds an
**overall merge-readiness verdict** and **baseline reasoning** + an `On
base?` column. |
| `azdo-build-investigator/SKILL.md` | Slimmed (~106→68 lines) to
reference the facts doc; keeps its unique value (ci-analysis-first, the
outdated-`maui-public` correction, escalation to `helix-investigation`).
|
| `Gather-TestFailureContext.ps1` | Extends the deterministic gatherer
with **per-test base-branch baseline extraction + comparison**
(`failures.baseline`, `baselineMatchCount`, `baselineSummary`,
`alsoFailsOnBaseline`). |
| `copilot-review-tests.md` (+ lock) | Output template gains a
**Baseline** badge, an `On base?` column, and merge-readiness
verdict/colors. |
| `Review-Tests.ps1` | Local runner: merge-readiness verdict→color map +
a Baseline badge from `failures.baselineMatchCount`. |
| `ci-status-main.md` / `ci-status-net11.md` (+ locks) | Removed
duplicated pipeline-ID table, "key points" bullets, failure-pattern
table, and dedup prose — now reference the facts doc; added a facts-doc
existence check to the connectivity probe. |

## Validation

- Both PowerShell scripts AST-parse cleanly.
- `gh aw compile` of all three workflows: **0 errors**, and a second
recompile is **idempotent** (no further lock diff) — the compiled
`.lock.yml` files are in sync with their `.md` bodies. (gh-aw
`{{#runtime-import}}`s the body and pins a `body_hash`, so body edits
surface as a hash-only lock diff.)
- Grep sweep confirms **no inline copies** of the canonical
pipeline/failure-pattern tables remain outside the facts doc, and the
facts-doc consumer list exactly matches the set of files that reference
it (bidirectional).

## Intentionally out of scope (follow-up)

A parallel "repo-health" analysis flagged a couple of broader items left
untouched here: the pipeline name→ID table is still duplicated in
`copilot-instructions.md` and `trigger-azdo-pipeline-setup`, and there
are some dead `pr` agent references in `copilot-instructions.md`. Those
are the next concentric ring of cleanup and aren't required for this
convergence.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The official `ci-official.yml` pack pipeline only builds and packs NuGet
packages — no tests run, so simulator runtimes are not needed. The
`Install Simulator Runtimes` step has been timing out on macOS agents,
blocking official builds.

Adds `skipSimulatorSetup: true` to the provision parameters in the pack
stage.

Backport of the same fix from `release/11.0.1xx-preview3` (#34801).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Problem

The `Merge net11.0 to next release` workflow silently does nothing when
triggered via `workflow_dispatch` or `schedule` because both run against
`main` (the default branch). The arcade merge script uses
`GITHUB_REF_NAME` as the config lookup key, finds no `"main"` entry in
`github-merge-flow-release-11.jsonc`, and exits with "There was no
configuration found for main" — but reports success.

## Fix

Add `if: github.ref_name == 'net11.0'` guard to the job so it skips
immediately when triggered from the wrong branch, instead of silently
succeeding.

**For `workflow_dispatch`**: Select `net11.0` from the branch dropdown
in the GitHub UI before clicking Run.

**For `schedule`**: The cron trigger always runs on the default branch
(`main`), so it will be skipped. The workflow on the `net11.0` branch
(triggered by `push`) handles the actual merges.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description

Fixes the broken `net11.0` → release down-merge automation. The `Merge
net11.0 to next release` workflow
(`.github/workflows/merge-net11-to-release.yml`) delegates to the shared
arcade `inter-branch-merge-base.yml`, which reads its merge-flow
configuration from the **default branch (`main`)** — the
`configuration_file_branch` input [defaults to
`'main'`](https://github.com/dotnet/arcade/blob/main/.github/workflows/inter-branch-merge-base.yml).

On `main`, `github-merge-flow-release-11.jsonc` still pointed at the
stale `release/11.0.1xx-preview4`. The bump to `preview6` (#36110) was
applied only to the copy on the `net11.0` branch, which the workflow
never reads. As a result the workflow targeted `preview4`, tried to
update the leftover stale `merge/net11.0-to-release/11.0.1xx-preview4`
branch, hit a non-fast-forward push rejection, and exited 1 on every
`push`-from-`net11.0` run — so no `preview6` down-merge PR was ever
created.

This one-line change updates the **main** copy to
`release/11.0.1xx-preview6` so the automation targets the current
preview release branch.

### Evidence

- Run
[`28241084988`](https://github.com/dotnet/maui/actions/runs/28241084988)
Merge step: `read-configuration.ps1 -ConfigurationFileBranch main …
github-merge-flow-release-11.jsonc` → `[MergeToBranch,
release/11.0.1xx-preview4]`, then non-fast-forward push rejection →
`WARNING: Failed to update existing PR` → exit code 1.
- `git show origin/main:github-merge-flow-release-11.jsonc` →
`preview4`; `git show origin/net11.0:…` → `preview6` (unread by the
workflow).
- `release/11.0.1xx-preview6` exists on origin, so this was a
stale-config issue, not a missing-branch issue.

### Follow-up (not in this PR)

Stale leftover branches `merge/net11.0-to-release/11.0.1xx-preview4` and
`…preview3` (and stale PR #34875) can be cleaned up separately. The
misleading comments in `merge-net11-to-release.yml` (claiming the config
is read from `net11.0`, and that the daily schedule works from
`net11.0`) are also worth revisiting, since scheduled workflows and
config reads both happen from the default branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### What this does

Adds a `push` tag trigger to the **Milestone Management** workflow
(`fix-milestone-drift.yml`) so that when a release tag (e.g. `10.0.80`)
is pushed, the workflow automatically audits the entire tag cohort,
fixes milestone drift, and closes issues fixed by PRs that shipped in
that tag.

Previously this was a manual `workflow_dispatch` exercise — someone had
to remember to run it against each tag. Now it runs as part of cutting a
release.

### Changes

**Workflow (`fix-milestone-drift.yml`)**
- **New `on.push.tags` trigger**, scoped to the `MAJOR.0.PATCH` shape
that .NET MAUI actually ships, with three globs so each ref shape gets
its own line (GitHub Actions filter patterns match the whole ref):
  - `1[01].0.[0-9]+` — stable SR / GA (e.g. `10.0.80`, `11.0.0`)
- `1[01].0.[0-9]+-preview.*` — preview (e.g. `11.0.0-preview.5.26304.4`)
  - `1[01].0.[0-9]+-rc.*` — rc (e.g. `10.0.0-rc.1.25424.2`)
- **Preview and RC tags are included** (deliberately). MAJOR is pinned
to a currently-supported major (10/11) and MINOR is pinned to `0` to
bound the blast radius — a stray tag like `1.2.3`, `7.0.0`,
`9.0.100-preview.1.9973` or `10.1.0` must **not** fire the bulk `-Apply`
path. The minor pin mirrors the script's own contract
(`Test-IsReleaseTag` is `^MAJOR\.0\.`), so a non-`.0` minor could never
resolve a milestone anyway.
- **Job `if`** now also runs for `push` events.
- **New `push` branch** in the run step invokes tag-mode with `-Apply
-CloseFixedIssues`, plus a defense-in-depth bash guard
(`^[0-9]+\.[0-9]+\.[0-9]+(-(preview|rc)\.[0-9]+(\.[0-9]+)*)?$`) that
hard-fails on any ref that isn't a release-tag shape (anti-injection
backstop; intentionally major-/minor-agnostic since the glob owns
scope). `github.ref_name` reaches the script only via the `PUSH_TAG` env
var and is passed as a discrete bash-array element — never `${{
}}`-interpolated into the run script.
- The existing **PR-merge** (`pull_request_target`) and **manual
`workflow_dispatch`** paths are unchanged.

**Script (`Fix-MilestoneDrift.ps1`)**
- **New `-MergedAfter` parameter** makes the previously-hardcoded
"merged-before" safety cutoff configurable (extracted into a pure,
unit-tested `Resolve-MergedAfterCutoff`). PRs merged strictly before the
cutoff are skipped; the default stays **2026-01-01** (when this
automation went live) so the bulk path can't reach back and rewrite
milestones for PRs that predate it. Override it to deliberately process
an older release locally — e.g. `-MergedAfter '2024-01-01' -Apply
-CloseFixedIssues` to close linked issues for a historical SR. This is a
local/manual knob only; it is **not** exposed through the workflow.

**Tests**
- `MilestoneTrigger.Tests.ps1` (new) — ~100 Pester tests covering the
tag-trigger: a self-tested GH-glob→regex translator driving a large
match/no-match fixture (stable/preview/rc that should fire; out-of-range
major, non-`.0` minor, and malformed shapes that should not), plus the
bash guard regex extracted verbatim from the YAML and run through real
`bash` against valid tags and injection payloads, plus
structure/injection-safety invariants.
- `Fix-MilestoneDrift.Tests.ps1` — +18 tests for
`Resolve-MergedAfterCutoff` (default/whitespace → 2026-01-01 UTC,
date-only and ISO-8601 parsing, invalid-input errors) and `Get-PrInfo`
cutoff enforcement (skip-before, include-after, exact boundary,
lowered/raised cutoff, unmerged PRs).

### Behavioral note

Tag-push events run the workflow file **as it exists at the tagged
commit**. So this trigger only takes effect for tags cut from commits
that already contain this change — i.e. after it merges to `main` and
flows into the `release/*` branches that SR tags are cut from. It will
not retroactively run on existing tags, and manual `workflow_dispatch`
remains available for any tag in the meantime.

A tag pushed using the default `GITHUB_TOKEN` does **not** trigger this
workflow (GitHub suppresses runs for events raised by the default token
to avoid loops). Release tags must be pushed by a human or by automation
using a PAT / GitHub App token. Today SR tags are pushed by a
maintainer, so it fires — documented inline so a future change to
tag-creation automation can't silently regress it.

### Validation

- YAML parses; run-step bash syntax verified
- Run-step branch logic verified for all cases: push of a release tag →
`-Tag <tag> -Apply -CloseFixedIssues`; non-release / non-`.0`-minor /
wrong-major refs → rejected; PR-to-`main` and PR-to-`net*.0` paths →
unchanged
- The underlying tag-mode `-Apply -CloseFixedIssues` invocation was
validated live against `10.0.80` (2 milestone corrections + 2 issue
closures, matching live GitHub state)
- Full Pester suite green (314 tests across both files)

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#35677)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Summary

- Posts MauiBot AI Summary output as a pull request review with parsed
`APPROVE`, `REQUEST_CHANGES`, or safe `COMMENT` fallback.
- Uses the new AI Review Summary layout with segmented status chips,
collapsed review sessions, and merged Future Action content.
- Keeps PR finalization out of the automated review process; AI Summary
updates no longer preserve or merge `SECTION:PR-FINALIZE` blocks.
- Adds visible AI Summary guidance telling users to comment `/review
rerun` after new comments or commits when they want a fresh review. The
command implementation is intentionally split into a follow-up PR.
- Hides stale MauiBot AI Summary / try-fix artifacts with GitHub
minimization instead of deleting them, while preserving same-run try-fix
and AI Summary reviews.
- Updates the Copilot pipeline to pass review IDs and patch review
bodies after deep UI tests.
- Hardens gate setup/retry handling by committing squashed PR changes
before verification, resetting the review branch before gate retries,
and detecting BlazorWebView unit-test project paths.

## Validation

- Parsed changed PowerShell scripts with
`System.Management.Automation.Language.Parser`.
- Parsed `.github/workflows/review-trigger.yml` as YAML.
- `Invoke-Pester
.github/scripts/Post-AISummaryComment.Tests.ps1,.github/scripts/Remove-StaleMauiBotComments.Tests.ps1
-CI`
- Dry-run AI Summary generation verified the rerun note, segmented
chips, and collapsed review session layout.
- Verified `Detect-TestsInDiff.ps1` maps
`src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs`
to
`src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj`.


## net11.0-targeting PR support

This branch also makes the Copilot review pipeline handle
**`net11.0`-targeting PRs** as well as `main`/net10, from a single
pipeline branch (consolidates and supersedes #35994):

- **Runtime base-branch auto-detection**
(`eng/pipelines/ci-copilot.yml`): the `CopilotReview` and `DeepUITests`
stages read the PR's `baseRefName` via `gh`, allowlist-validate it
(`^(main|net[0-9]+\.0)$`), and check out that base **before** workload
install and the squash-merge — so workloads (net11 `11.0.100` vs net10
`10.0.100`) and the merge base follow the PR. Trusted scripts are
captured from the pipeline ref first (security rule 3); Task 1 Setup
runs from `$TRUSTED`.
- **Branch-aware test TargetFramework**: `BuildAndRunHostApp.ps1` and
`run-device-tests/Run-DeviceTests.ps1` now derive the TFM from
`Directory.Build.props` (`Get-MauiTfmVersion` in `shared-utils.ps1`)
instead of hardcoding `net10.0`, so deep-UI/device tests build
`net11.0-android` on net11. The `DeepUITests` stage restores the
reviewed pipeline-branch scripts over the worktree before the
per-category loop.

`main`/net10 behavior is unchanged by design (base-detection checks out
`main` = the original flow; `global.json` stays `10.0.108`).
`review-trigger.yml` and `Review-PR.ps1` are intentionally untouched.

**Validation:** 8 live net11 runs with 100% correct base detection (e.g.
#35891 gate ran net11 Core tests 44/45 → 45/45, conflict-free
squash-merge onto net11.0); reproduced and root-caused a separate
net11.0-baseline `MAUIX2017` Xaml.UnitTests build break (unrelated to
this change). Confirmation runs from this branch cover one net11 PR and
one main PR.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tomas Grosup <tomasgrosup@microsoft.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot CI <copilot-ci@microsoft.com>
Co-authored-by: kubaflo <kubaflo@users.noreply.github.com>
…rkitems endpoint (#36185)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Problem

The `/review tests` agentic-workflow gather script confirmed device-test
(`maui-pr-devicetests`) results via the Helix **`/aggregated`**
endpoint. That endpoint returns **HTTP 404 anonymously** (verified
against live maui jobs), and the gh-aw runner is **unauthenticated**. So
the read *always* threw, device tests were **never** positively
confirmed, and every green device-test check fell to
`gate.deviceTestUnverified` — hard-capping verdicts to **Needs Human
Investigation**.

This surfaced as confusing "device-unverified / Not authenticated" caps
after #36067 (e.g. on #31661 and #34408). The convergence PR didn't
*introduce* the gap — it made an always-failing path visible. This fixes
the underlying data source so device tests are actually confirmable with
**zero auth**.

### Fix

Switch device-test confirmation to the per-job **`/workitems`** endpoint
(reachable anonymously), plus job detail (`/jobs/{id}`) for completeness
signals (`InitialWorkItemCount`, job `Finished`). Add **green-leg Helix
job discovery** so a *green* leg's hidden work-item failure is caught —
XHarness exits 0 even when a Helix work item fails, so a green AzDO leg
can hide a real device failure.

### Never a false green

The change preserves the core invariant — any incompleteness caps the
verdict, it never positively confirms over unobserved data:

- **Reset `$records` per build** so a build whose timeline read fails
cannot inherit the *previous* build's legs and false-confirm.
- **A green `Job` leg with no discoverable Helix job caps** (no
work-item evidence ⇒ a sibling's clean job can't confirm over it).
Scoped to `type=='Job' && result=='succeeded'` so it doesn't over-block
the duplicate `Phase` records or already-failing red legs.
- **Missing/non-int `InitialWorkItemCount`, a short work-item set, a
not-yet-`Finished` job/item, or a non-array response ⇒ `unverified`.**
- **A green check is confirmed only if EVERY backing build confirmed
`Failed==0`** (≥1 confirmed AND none unconfirmed) — a clean
re-run/sibling can no longer mask an unverified build under the same
check name. A canceled backing build is excused only because it's
already capped by the canceled-check ceiling.

### Validation (all live, anonymous — mirrors CI)

- `pwsh` parse OK; **28/28** unit tests pass (added a harness for the
new work-item counter).
- Build `1483259` (clean) ⇒ positively confirmed — **the happy path is
not over-blocked**.
- Build `1483473` ⇒ **no spurious green-Job cap** (all green legs
discovered jobs).
- Build `1483277` — **AzDO-"succeeded"** yet its Windows Helix job had
**12 work items at `ExitCode=-4`** with the job not `Finished` ⇒ now
correctly **capped to NHI with all 12 failures surfaced**. The old
`/aggregated` (404) code could never see this false-green.

### Files

-
`.github/skills/review-test-failures/scripts/Gather-TestFailureContext.ps1`
— replace `/aggregated` scanner with `Get-HelixWorkItemCounts`,
green-leg discovery, completeness vetoes, AND-semantics check consumer.
- `.github/docs/maui-ci-facts.md` — document `/workitems` (the reachable
endpoint) and the anonymous `/aggregated` 404.

No product/runtime code changes — agentic-workflow tooling only.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

The `Microsoft.Maui.Essentials.AI` package has moved to
`dotnet/maui-labs` in dotnet/maui-labs#171, but
the source and build wiring were still present in `dotnet/maui`. We
probably forgot to remove the original copy after the move, which
allowed official MAUI builds to keep producing
`Microsoft.Maui.Essentials.AI` packages from this repository.

This removes the leftover Essentials.AI implementation from
`dotnet/maui` so `dotnet/maui-labs` is the package's home.

## Changes

- Delete the `src/AI` source, tests, sample app, docs, and native
binding assets.
- Remove Essentials.AI projects from the solution files and package
solution filters.
- Remove Essentials.AI package/build metadata, device-test pipeline
wiring, Helix entries, and helper-script project maps.
- Remove no-longer-used AI package version/dependency metadata from the
MAUI repo.

## Review

@mattleibow could you review this cleanup and confirm this matches the
intended move to `dotnet/maui-labs`?

## Validation

- No remaining `Essentials.AI` / `src/AI` references outside deleted
files.
- `dotnet msbuild eng/Microsoft.Maui.Packages-mac.slnf /t:Restore
/p:Configuration=Release /p:ValidateXcodeVersion=false
/p:EnableWindowsTargeting=true /v:minimal`
- `dotnet build eng/Microsoft.Maui.Packages-mac.slnf --configuration
Release --no-restore /p:ValidateXcodeVersion=false
/p:EnableWindowsTargeting=true --verbosity minimal`
- `dotnet msbuild Microsoft.Maui-mac.slnf /t:Restore
/p:Configuration=Debug /p:ValidateXcodeVersion=false
/p:EnableWindowsTargeting=true /v:minimal`
- `git diff --check`

Note: `dotnet msbuild Microsoft.Maui.sln /t:Restore ...` was also
attempted, but this local environment is missing the `macos` workload
required by existing Graphics sample projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Summary
- Updates the sample-content MAUI template to use
`CommunityToolkit.Mvvm` 8.4.2.
- Converts template page models from field-backed `[ObservableProperty]`
members to partial observable properties without enabling preview
language features.
- Switches the sample-content SQLitePCLRaw dependency from
`bundle_green` to `bundle_e_sqlite3` 3.0.3 and updates cgmanifest
version mapping so generated projects avoid default NuGet audit
warnings.

## Validation
- `dotnet build .\src\Templates\src\Microsoft.Maui.Templates.csproj
-p:UpdateCgManifestBeforeBuild=false -p:GenerateCgManifest=false`
- Packed templates and generated a `dotnet new maui --sample-content
true` app from an isolated template hive.
- `dotnet build <generated app> -f net10.0-windows10.0.19041.0
-p:RestoreIgnoreFailedSources=true` completed with 0 warnings and 0
errors, with no generated `LangVersion` or `EnablePreviewFeatures`
entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ll (#36268)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### What this adds

A **public-safe "Preview release readiness"** capability in the
`dependency-flow` skill. This is a docs/skill + script authoring change
only — **no API changes, no dependency bumps**.

**Two files:**

1.
**`.github/skills/dependency-flow/scripts/Get-PreviewReleaseReadiness.ps1`**
— a deterministic access gate. It runs a single local `gh api
repos/dotnet/release --silent` read probe and checks the user's personal
`~/.copilot/settings.json` for an enabled `dotnet-release-tracker`
plugin (tolerant of any marketplace suffix). It emits exactly one status
line to stdout and **always exits 0** so it can never fail its caller:
   - `RELEASE_TRACKER_STATUS=NO_ACCESS`
   - `RELEASE_TRACKER_STATUS=AVAILABLE_ENABLED`
   - `RELEASE_TRACKER_STATUS=AVAILABLE_NOT_ENABLED`

2. **`.github/skills/dependency-flow/SKILL.md`** — a new **"## Preview
release readiness"** section (appended; existing content untouched)
documenting how to run the gate and how to branch on the token.

### A/B/C tiering

- **AVAILABLE_ENABLED** → use the private `dotnet-release-tracker`
plugin as the authoritative source.
- **AVAILABLE_NOT_ENABLED** → the user appears to have access; offer a
**personal** opt-in snippet for their own `~/.copilot/settings.json`
(never commit plugin enablement to the repo).
- **NO_ACCESS** → silently fall back to the existing public BAR/Maestro
workflow, **without ever revealing that a private source exists**.

### Privacy / security guardrails

- **No secrets, no internal URLs, no AAD/tenant GUIDs, no endpoint
hostnames** anywhere in either file. The only private coordinate
referenced is the repo name `dotnet/release`, used purely for the access
probe.
- **No fetch-and-exec** — the gate only runs a local `gh api` read check
and prints a status token; the probe body and stderr are discarded so no
private data leaks to stdout.
- Access is **double-gated** (GitHub read on `dotnet/release` + an
authorized AAD identity handled by the plugin, not by this script).
- The private source is **invisible to no-access users**.

### Honest public-data limitation

Public data (BAR/Maestro + `dotnet/core` metadata) can surface
build/channel/coherency and subscription health, but **cannot identify
which staged build is "blessed"** as the official preview — that
determination lives in the authoritative source. The doc calls this out
explicitly for the no-access and un-enabled tiers.

### Testing performed

- Real run on a machine **with** access, plugin not enabled →
`AVAILABLE_NOT_ENABLED`, exit 0, exactly one line.
- No-access simulation (temp copy probing a nonexistent repo) →
`NO_ACCESS`, exit 0, one line; original script untouched.
- Missing `gh` on `PATH` → `NO_ACCESS`, exit 0.
- Enabled-detection across settings variations (any marketplace suffix /
no suffix / value `false` / unrelated plugin / missing file / malformed
JSON / no `enabledPlugins` key) — all correct and always exit 0.
- PowerShell parse check: no syntax errors.
- Guardrail scan: no suspicious URLs and no GUIDs in the new files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…2E refresh, and hoisted candidate-PR section (#36172)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Summary

A set of related improvements to the release-readiness tooling
(`.github/skills/release-readiness/`). Four logical changes, all
additive, spanning the preview engine, the SR engine, and the shared
test suite:

1. **Fix a cross-major `previewN` scope leak** (preview engine)
2. **Flag a missing preview milestone as a ship-readiness blocker**
(preview engine)
3. **Hoist the SR "Candidate PR" into a prominent readiness section**
(SR engine)
4. **Refresh drifted E2E snapshot assertions** to current release state
(tests)

Full suite runs **758/0** locally (offline). Files changed:
`Get-PreviewReadiness.ps1`, `Get-ReleaseReadiness.ps1`,
`Test-ReleaseReadiness.ps1`.

---

### 1. Cross-major preview-number leak

A `.NET 10` `p/0` regression issue (**#31960**) was surfacing as a 🔥
**P/0 blocker** on the **.NET 11 preview7** tracker.

**Root cause** — `Test-IssueReleaseRelevant`
(`Get-PreviewReadiness.ps1`) accepts an issue if its
title/milestone/labels contain a bare `previewN` substring:

```powershell
if ($haystack -match "(?i)preview\s*$Preview|preview$Preview") { return $true }
```

That match is **major-ambiguous** — every major has a `previewN`. The
regression label `regressed-in-10-preview7` (a **.NET 10** label,
milestone `.NET 10 SR12`) matched when surveying **.NET 11** preview7,
leaking #31960 onto the wrong tracker.

**Fix** — add `Test-IssueHasForeignMajor`: when a `previewN` match is
found, reject it if the issue carries a **contradicting foreign-major
signal** — a `regressed-in-<M>-*` label, a `.NET <M>` milestone, or an
`<M>.0` token whose major differs from the surveyed major. Majors are
bounded to `6..99` so build numbers (e.g. `…preview.7.26324.11`) can't
register as a major. The detector is anchored to `.NET`-shaped tokens
only (review round `3dfac6ceca`). The wide net is intentionally
preserved: genuinely major-less `previewN` mentions stay relevant, and
same-major issues are still caught by the existing major signal first.

### 2. Missing preview milestone → ship blocker

If a preview tracker is generated but the corresponding GitHub milestone
doesn't exist yet, that's a real gap — the milestone must be created
**right away**, not at cut time. The preview engine now emits a **P/0
ship-readiness blocker** on the tracker when the expected milestone is
absent, so it can't be silently forgotten.

### 3. Hoisted SR "Candidate PR" section

In SR **candidate (pre-cut) mode**, the single most important PR in the
cycle is the open **"Candidate" PR** that promotes a specific `main`
commit as the SR cut point — the SR branch can't be cut until it merges.
It was previously buried as a lone `WATCH` row in the bottom ship-checks
table plus a sparse low section.

It's now surfaced directly **under the Blocking summary** as a `## 🚩
Candidate PR — SRx cut point (10.0.x0)` section with:
- A live status table: 🟢 Open · ✅ Ready/📝 Draft · mergeable/⚠️
conflicts, **PR age** ("2026-06-08 (26 days ago)"), last-update, and
review decision.
- A **staleness callout** (`⚠️ Stale (N days old)` once ≥14 days) tied
to the ship-target date — a long-open cut PR likely points at a
now-stale `main` commit.
- The **SR version base** (e.g. `10.0.90`) derived from the prior SR
branch (`…-sr8` → SR9 → `targetSr*10`).

Design details:
- New `Get-CandidatePrResolution` runs the `gh` query + maintainer
spoof-gate **once** per report; both the `WATCH` ship-check and the
section consume the shared result (`$data['candidatePr']`) — no
duplicate round-trips, no twin-drift.
- Verdict semantics **unchanged**: an open/missing candidate PR stays
`WATCH` (normal cycle hygiene), never `BLOCKED`. The captain decides
when to merge.
- `candidatePr` is JSON-serialized for downstream automation but
**excluded from the semantic hash**, so the daily-ticking age text
doesn't churn the tracker.
- The noisy open-main-PR dump is now suppressed in candidate mode (kept
for live-SR mode); the section links only the maintainer-gated
candidate(s) plus a pointer to the full PR list.
- Maintainer spoof-gate is fail-closed: an unreadable
`author_association` excludes the PR and is counted as `unverifiable`
(distinct from a confirmed non-maintainer `spoofer`), so a transient
blip during a real cut isn't mislabeled.

### 4. E2E snapshot refresh

Refreshes drifted end-to-end snapshot assertions in the test suite to
match current release state, fixing failures caused by real-world
release progression rather than code changes.

---

### Tests

- **Cross-major (12 assertions):** the exact #31960 shape is **not**
relevant for Major 11 / preview7 but **is** for its own Major 10 /
preview7; same-major keep-cases; bare-mention wide-net; build-number
poisoning guard; the preview6 variant; direct
`Test-IssueHasForeignMajor` coverage.
- **Candidate-PR section:** migrated the renderer tests to the hoisted
section (the human-notes marker-forgery defense is re-pointed at the
candidate table cell so it's still exercised); added 16
`Get-CandidatePrResolution` unit tests (mode transitions, version-base
derivation, spoofer vs unverifiable classification, query-failed/skip
short-circuits).
- Full suite: **758/0** offline.

### Scope

Additive across three files in `.github/skills/release-readiness/`. No
behavior change for genuinely same-major issues, and SR verdict
semantics are unchanged (candidate PR stays `WATCH`).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reset patterns:
- global.json
- NuGet.config
- eng/Version.Details.xml
- eng/Versions.props
- eng/common/*
@kubaflo kubaflo closed this Jul 18, 2026
PureWeen pushed a commit that referenced this pull request Jul 20, 2026
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

Retires automation targeting the unsupported `net10.0` branch:

- Removes the scheduled/event-driven `main` → `net10.0` merge workflow
and its configuration.
- Removes `net10.0` from the daily formatting workflow matrix.
- Disables the live merge workflow immediately to prevent replacement
PRs while this change is reviewed.

The matching dependency-flow cleanup is tracked by
[maestro-configuration PR
63025](https://dev.azure.com/dnceng/internal/_git/maestro-configuration/pullrequest/63025),
removing the Android, dotnet, and macios subscriptions plus the
`net10.0` default-channel mapping.

### Issues Fixed

No issue. Retires the automation responsible for generated PRs #36400
and #36641.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SyedAbdulAzeemSF4852 pushed a commit to SyedAbdulAzeemSF4852/maui that referenced this pull request Jul 27, 2026
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

Retires automation targeting the unsupported `net10.0` branch:

- Removes the scheduled/event-driven `main` → `net10.0` merge workflow
and its configuration.
- Removes `net10.0` from the daily formatting workflow matrix.
- Disables the live merge workflow immediately to prevent replacement
PRs while this change is reviewed.

The matching dependency-flow cleanup is tracked by
[maestro-configuration PR
63025](https://dev.azure.com/dnceng/internal/_git/maestro-configuration/pullrequest/63025),
removing the Android, dotnet, and macios subscriptions plus the
`net10.0` default-channel mapping.

### Issues Fixed

No issue. Retires the automation responsible for generated PRs dotnet#36400
and dotnet#36641.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.