[automated] Merge branch 'main' => 'net10.0' - #36400
Closed
github-actions[bot] wants to merge 917 commits into
Closed
[automated] Merge branch 'main' => 'net10.0'#36400github-actions[bot] wants to merge 917 commits into
github-actions[bot] wants to merge 917 commits into
Conversation
<!-- 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>
### Issues Fixed Fixes #26397 Fixes #33501 |Before|After| |--|--| |<video src="https://github.com/user-attachments/assets/c5edf988-a6fd-476e-9cb9-235bc72d47a4" width="300px"/>|<video src="https://github.com/user-attachments/assets/b70a4dd3-2406-430b-add5-ab60a73a4f66" width="300px"/>| ---------
> [!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. --> ---------
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> [](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/*
This was referenced Jul 6, 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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.
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.
or if you are using SSH
After PR checks are complete push the branch
Instructions for resolving conflicts
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.
or if you are using SSH
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.