Skip to content

[automated] Merge branch 'net11.0' => 'release/11.0.1xx-preview7' - #36986

Merged
PureWeen merged 57 commits into
release/11.0.1xx-preview7from
merge/net11.0-to-release/11.0.1xx-preview7
Aug 3, 2026
Merged

[automated] Merge branch 'net11.0' => 'release/11.0.1xx-preview7'#36986
PureWeen merged 57 commits into
release/11.0.1xx-preview7from
merge/net11.0-to-release/11.0.1xx-preview7

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

I detected changes in the net11.0 branch which have not been merged yet to release/11.0.1xx-preview7. I'm a robot and am configured to help you automatically keep release/11.0.1xx-preview7 up to date, so I've opened this PR.

This PR merges commits made on net11.0 by the following committers:

  • TamilarasanSF4853
  • SubhikshaSf4851
  • PureWeen
  • Copilot
  • Redth
  • kubaflo
  • kevin68
  • github-actions[bot]
  • rmarinho
  • mattleibow

Instructions for merging from UI

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

merge button instructions

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

Instructions for merging via command line

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

git fetch
git checkout net11.0
git pull --ff-only
git checkout release/11.0.1xx-preview7
git pull --ff-only
git merge --no-ff net11.0

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

After PR checks are complete push the branch

git push

Instructions for resolving conflicts

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

Instructions for updating this pull request

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

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

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.

mattleibow and others added 24 commits May 21, 2026 23:45
Adds docs/specs/shell-route-templates.md with the full design for additive
{param} path parameters in Shell routes (issue #35107 Proposal A), and a
standalone prototype at prototype/ShellRouteTemplates that demonstrates the
parser, matcher, and precedence rules independently of MAUI internals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds support for route templates like 'product/{sku}' in Shell
navigation, allowing path parameters to be extracted from URIs and
delivered to pages via [QueryProperty] / IQueryAttributable.

Key changes:
- RouteTemplate.cs: template parser and segment helpers
- Routing.cs: detect and store template routes alongside literal routes
- RouteRequestBuilder.cs: template-aware segment matching with parameter capture
- ShellUriHandler.cs: two-pass matching (literal-first precedence),
  template-aware CollapsePath
- RequestDefinition.cs: exposes PathParameters from winning route
- ShellNavigationManager.cs: seeds path params before query string params

All 5551 existing unit tests pass unchanged. 8 new tests added.

Ref: #35107

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oss, add 9 new tests

Review findings addressed:
- Reject {sku?} optional and {*path} catch-all syntax at registration
  time (not yet implemented, was silently accepted)
- Reject duplicate parameters in templates ({id}/{id})
- Fix path parameter loss in SearchForGlobalRoutes code path
- Fix path parameter loss in GenerateRoutePaths tree+global merge
- Fix GlobalRouteItem AddMatch missing _resolvedGlobalRoutes entry
- Fix IndexOutOfRange in RequestDefinition.MakeUriString
- Add ShellSection.GetOrCreateFromRoute resolved-route override for
  template routes (CurrentState.Location fix)

9 new tests (17 total):
- CurrentState.Location shows resolved values, not template tokens
- Relative navigation limitation documented
- URL-encoded path parameters decoded correctly
- Second navigation with different value
- Reject optional/catch-all/duplicate template syntax
- IQueryAttributable receives path parameters
- All-template route ambiguity documented

All 5560 existing + new tests pass, 0 regressions.

Sandbox demo added with ProductPage, ReviewPage, and navigation buttons.

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

Full route template feature set now implemented:
- {sku?}       Optional parameters (match zero or one segment)
- {*path}      Catch-all (captures all remaining segments, must be last)
- {id:int}     Constraints (int, long, double, bool, guid, alpha)
- {stars=5}    Default values (provided when segment absent)
- product-{sku} Mixed segments (literal prefix/suffix around parameter)
- {id:int=1}   Constraint + default combined

Sandbox demo updated:
- Products tab: catalog with product/{sku} route
- Orders tab: order list with order/{orderId:int} constrained route
- Product review: review/{stars=5} with default star rating
- Multi-step navigation: product → review with inherited parameters

48 template tests (31 new), 5591 total tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
67 template tests now cover all features in various combinations:
- Two params in single route ({cat}/{id})
- Required + optional combos
- Optional + constraint ({id:int?})
- Optional with query string fallback
- Default value + query string interaction (default wins)
- Default value + child page inheritance
- Catch-all with URL encoding
- Catch-all with empty remaining segments
- Mixed segment + constraint (item-{id:int})
- Mixed segment prefix mismatch rejection
- Constraint + literal precedence
- Two different templates in same navigation
- Template + literal route together
- Unregister template route lifecycle
- Constraint unit tests: bool, long, double, guid-reject

5610 total tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bugs fixed (from Opus 4.7 + GPT 5.4 reviews):
- BLOCKING: {name:int?=5} produced default '5?' instead of '5' due to
  appending '?' to inner string during constraint parsing. Fixed by using
  a separate boolean flag.
- Optional params in middle of route (e.g. a/{b?}/c) now rejected at
  registration time (matches ASP.NET Core behavior — unmatchable).
- Default values now validated against constraint at registration time
  (e.g. {id:int=hello} is now rejected).
- Multiple brace pairs in mixed segments (e.g. item-{x}-{y}) now rejected.
- IsTemplateSegment now requires { before } (rejects 'foo}bar{baz').
- Sandbox demo fixed to use absolute URIs (relative template nav unsupported).

7 new tests (74 total):
- Parse_ConstraintOptionalAndDefault_Combo — verifies {num:int?=5} combo
- RegisterRoute_RejectsDefaultThatViolatesConstraint
- RegisterRoute_RejectsOptionalInMiddle
- RegisterRoute_RejectsMultipleParamsInMixedSegment
- Parse_MalformedBraces_Rejected
- Parse_EmptyParameterName_Rejected
- Parse_ConstraintWithNoName_Rejected

5617 total tests pass, 0 regressions.

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

Critical fixes from Opus 4.7 + GPT 5.4 round 3:

1. Template lookup bypass (Opus blocking): When CollapsePath stripped
   prefix segments, GetNextSegmentMatch looked up the template by the
   collapsed key (e.g. '{id:int}') instead of the registered key
   ('orders/{id:int}'), so constraints/defaults/catch-all were silently
   bypassed. Fixed by passing RouteTemplate directly from the caller.

2. SetRoute mutation (Opus blocking, GPT medium): Mutating Page.Route
   from template key to resolved value broke stack-reuse comparisons
   (Routing.GetRoute(page) == globalRoutes[i] always false), causing
   page recreation on re-navigation. Fixed with separate
   Routing.ResolvedRouteProperty — Route keeps the template key,
   ResolvedRoute stores the resolved URI for CurrentState.Location.

3. RequestDefinition.FullUri (Opus warning): Built from unresolved
   template tokens ('{sku}'), causing ShellNavigationSource
   misclassification. Fixed to use ResolvedGlobalRoutes when available.

4. Back navigation: Updated .. path and GetNavigationState to use
   ResolvedRoute ?? Route for correct URI reconstruction.

3 new tests (77 total):
- TemplateRoute_RenavigationPreservesPageInstance
- Constraint_EnforcedWhenShellContentMatchesPrefix
- Constraint_AcceptedWhenShellContentMatchesPrefix

5620 total tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…te params, FullUri

Fixes from Opus 4.7 + GPT 5.4 round 4:

1. IL2111 trimmer error (Opus blocking): ResolvedRouteProperty field
   initializer caused trimmer warning→error. Fixed by wrapping in
   CreateResolvedRouteProperty() with [UnconditionalSuppressMessage].

2. Stale ResolvedRoute on reused pages (GPT high): When re-navigating
   to same template route with different value, the reused page kept
   the old ResolvedRoute. Fixed by updating ResolvedRoute in the
   page-reuse check at PrepareCurrentStackForBeingReplaced.

3. Intermediate page parameter delivery (GPT high): Non-last pages
   in navigation chain now receive route-prefixed path params
   (e.g. 'product/{sku}.sku') for prefix-filtered ApplyQueryAttributes.

4. Path params overwriting caller params (Opus medium): Changed from
   unconditional overwrite to 'only add if not present', matching
   SetQueryStringParameters semantics.

5. RequestDefinition.FullUri (Opus medium): Only substitute resolved
   route when the route is actually a template (IsTemplateRoute check),
   preventing multi-segment literal route truncation.

6. ExpandOutGlobalRoutes cast (Opus medium): Replaced fragile
   'as IDictionary' cast with MergePathParameters() helper.

4 new tests (81 total):
- IntermediatePage_ReceivesOwnPathParameter
- ReusedPage_ResolvedRouteUpdated
- OptionalParam_WithCollapsedPrefix_NavigationSucceeds
- DefaultParam_WithCollapsedPrefix_NavigationSucceeds

5624 total tests pass, 0 regressions.

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

Fixes from Opus 4.7 + GPT 5.4 round 5:

1. Tautological tests fixed: IntermediatePage, DefaultWithChild,
   OptionalParam_WithCollapsedPrefix, DefaultParam_WithCollapsedPrefix
   all now assert meaningful conditions instead of always-true checks.

2. Modal-stack reuse path: ResolvedRoute is now also updated in the
   pop/reapply loop (ShellSection.cs line 417 path), not just the
   non-modal PrepareCurrentStackForBeingReplaced path.

3. Route-prefixed param seeding uses 'only add if not present'
   semantics, matching the same precedence rule as unprefixed params.

5624 total tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Samples integration tests build with TreatWarningsAsErrors=true.
Backing fields for QueryProperty properties in ProductPage, ReviewPage,
and OrderDetailPage were non-nullable, causing CS8618 warnings→errors.

Fixed by making all backing fields and properties nullable (string?).

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

- inject canonical CI-scan fingerprint, match-count, and trusted
evidence-key markers in the deterministic publisher instead of relying
on agent-authored HTML comments
- apply the same complete-manifest, frozen-evidence, all-or-nothing
publisher architecture to both `ci-status-main` and `ci-status-net11`
- separate countable raw failure evidence from synthetic provenance
framing and bind canonical recurrence to publisher-derived full
raw-evidence lines
- normalize run-specific AzDO transport timestamps only for trusted
`azdo-log` evidence, while preserving timestamps in non-AzDO failure
messages
- reject markerless issues as authoritative coverage and remove
automatic markerless adoption, preventing shared boilerplate from
suppressing a distinct failure
- recognize legacy pipeline lines with no suffix, `(ID N)`, or live
`(definition N)` syntax using the trusted configured pipeline definition
- reject pre-existing/evasive marker content and marker-like
`match_pattern` variants; revalidate exact post-injection payloads at
the GitHub write boundary
- require complete Helix terminal evidence and bind deadletter
placeholders to stable trusted work-item identity
- align the merged report-only reconciler invariants with
publisher-owned marker publication
- add twin-aware publisher/collector execution tests and named mutation
coverage for every security control

## Root cause

[PR #36848](#36848) added fail-closed
manifest validation to the net11 scanner and exposed a pre-existing
repo-wide publication defect. In [run
30413273824](https://github.com/dotnet/maui/actions/runs/30413273824),
the agent job succeeded, but `submit_ci_scan` failed before any issue
write because the compiled prompt did not contain the authored
HTML-comment marker template.

Artifact `agent` (`8709769921`) contained 16/16 signatures with zero
fingerprint-marker-prefix and zero canonical-marker matches. gh-aw
strips literal HTML comments while compiling the authored prompt, so
regenerating the lock or strengthening prompt prose cannot make
agent-side marker emission reliable. Output-side safe-output stripping
is not needed to explain this incident.

Main had the same silent blast radius: sampled issues #36858, #36779,
#36709, and #36689 carry no fingerprint marker, but its permissive
publisher did not validate the payload. Net11's all-or-nothing gate
correctly prevented every write, so the first post-merge run published
zero issues.

## Architecture

The shared trusted validator resolves a hard-coded scanner configuration
for `ci-scan|main` or `ci-scan-net11|net11.0`. For each filed manifest
entry it:

1. validates fingerprint provenance, body shape, complete manifest
coverage, frozen build/log provenance, and the five-issue mutation cap
2. rejects pre-existing fingerprint/match-count/evidence-key content and
marker-like `match_pattern` variants, including spacing, case,
zero-width, separator, HTML-comment-like, and Unicode-homoglyph evasions
3. counts matches only in structured `.evidence.json` raw segments;
rendered `.log` files retain AzDO/Helix provenance for diagnosis, but
synthetic headers are not countable evidence
4. normalizes and hashes each complete raw line containing the match
pattern, derives a domain-separated SHA-256 evidence key, and requires
the issue body to contain a complete trusted raw-evidence line
5. injects exactly one fingerprint marker from the validated manifest,
one match-count marker from the trusted recount, and one evidence-key
marker from the trusted raw-line hashes
6. validates the exact post-injection body before producing the plan

AzDO's log API prepends a different UTC transport timestamp to each
stored line on every build. PowerShell strips that prefix only when
structured provenance says the segment is `azdo-log`; Helix and other
message timestamps remain identity-bearing. At the write boundary,
publisher body matching computes both raw and AzDO-normalized candidates
against the trusted plan hash. The same failure therefore keeps its
evidence identity across builds while real non-AzDO timestamps remain
distinct.

Both compiled publisher jobs bind the plan to their trusted scanner ID,
branch, and label; preflight every issue/reference before any mutation;
preserve canonical marker retry/dedup; and revalidate GitHub's stored
response. Canonical recurrence requires the exact fingerprint and
evidence-key markers plus a current trusted evidence line.

Markerless legacy issues no longer provide authoritative coverage. Their
exact pipeline/evidence shape is still recognized for a precise
migration error, including no suffix, `(ID N)`, and the live
`(definition N)` suffix with the correct configured definition. An
explicit markerless `existing` reference aborts before any write, and a
`filed` payload never auto-adopts a markerless issue. It instead creates
bounded visible canonical coverage. This is intentionally safer than
silently merging two same-pipeline failures that share boilerplate such
as `Build FAILED.`

The frozen evidence collector treats a Helix job as complete only when
the job has a terminal `Finished` value, `Waiting` and `Running` are
zero, and every returned work item is terminal with valid completion
evidence. Helix's cumulative `Unscheduled` counter may remain nonzero
after completion and is validated but not treated as active work. AzDO
build records with missing or invalid `finishTime` fail closed.
Structured evidence enforces matching producer/consumer caps of 200
segments, 25 MB, and 200 distinct matching lines.

A deadletter placeholder URL contains no run-specific diagnostics and is
constant across Helix. The countable evidence line includes the
validated stable work-item name plus that URL. This distinguishes
unrelated work items while deliberately excluding job/build IDs so
recurrence for the same work item remains stable across builds.
Deadletters still mark their AzDO submission log as a failed leaf, so
absence-only coverage remains forbidden.

The branch is based on current `main` after PR #36850. Its report-only
reconciler asserts that both scanner twins compile trusted validation
before publisher-side exact-marker checks, rather than expecting an
agent marker template. The reconciler still has no production
state-marker writer, so stale-issue closure candidates remain
unreachable.

## Review findings resolved

- **Universal synthetic evidence header:** confirmed; synthetic framing
is structurally excluded from countable evidence.
- **Marker-like match replay:** confirmed; marker-like patterns fail
across exact, spacing, case, zero-width, and homoglyph variants.
- **Constant deadletter identity:** confirmed; fixed placeholder content
is bound to trusted stable work-item identity.
- **AzDO timestamp-sensitive identity:** confirmed; trusted `azdo-log`
transport timestamps are removed symmetrically from PowerShell proof
generation and JavaScript body matching.
- **Live legacy `(definition N)` suffix:** confirmed; exact no-suffix,
`(ID N)`, and `(definition N)` forms are recognized for all three
configured pipelines and both twins, and a wrong definition is rejected.
- **Generic markerless evidence collision:** confirmed; markerless
explicit coverage and automatic adoption are disabled rather than
relying on fragile length/entropy heuristics.
- **Helix active counts:** confirmed defense-in-depth; terminal evidence
requires zero `Waiting` and `Running` while allowing cumulative
`Unscheduled`.
- **Concurrency overlap note:** not reproduced. A fixed GitHub
concurrency group permits one running and one pending run;
`cancel-in-progress: false` preserves the active publisher instead of
allowing overlap.
- **Benign marker prose over-folding:** intentionally unchanged. Its
false-positive mode is an all-or-nothing batch abort, not silent issue
suppression.

## Tests

- strict `gh aw compile` for both twins: **0 errors, 0 warnings**
- focused validator/publisher/mutation Pester: **225/225 passed**
- complete `.github/scripts` Pester: **1489/1489 passed**
- repeated strict compilation produced unchanged lock hashes
- lock-extracted Node tests execute both compiled publishers and
collectors, including raw-vs-synthetic evidence, canonical cross-build
recurrence, markerless no-adoption/no-write behavior, exact legacy
pipeline formats, unrelated deadletter replay, Helix terminality,
no-partial-write batches, retry behavior, evidence caps, and twin
symmetry
- named mutations cover timestamp-sensitive identity, missing
`(definition N)` support, re-enabled markerless explicit coverage,
re-enabled markerless auto-adoption, removed injection, untrusted
fingerprint/count sourcing, pre-injection-only validation, duplicate
rejection removal, synthetic framing, marker-pattern rejection,
trusted-state recurrence, evidence-identity removal, constant deadletter
identity, omitted twins, and empty discovery
- independent final code review found no high-confidence defects

There is no scanner-specific gh-aw behavioral eval runner in this
repository, so deterministic Pester, lock-extracted Node execution,
strict compilation, and static anti-vacuity invariants provide
behavioral regression coverage.

### Residual risk

Disabling markerless adoption can produce a bounded visible duplicate
for a legacy issue until canonical coverage exists. This is intentional:
without a publisher-owned historical identity, silently reusing a
markerless issue is not a trustworthy dedup decision. Conservative
marker-content and evidence-size gates may also fail an entire scan
rather than truncate or publish partial evidence. These behaviors fail
closed and produce zero partial writes.

No real `ci-scan` or `ci-scan-net11` issue was mutated during
development or validation.

### Issues Fixed

No scanner tracking issue is closed by this infrastructure correction.
Related incident: PR #36848 and Actions run 30413273824.
<!-- 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!

Ports the `.cab` signing fix from #36879 (merged into
`release/11.0.1xx-preview7`) to `main`.

### Duplicate `.cab` signing entry

The internal `Pack, Sign` task fails with:

```
Sign.proj(74,5): error : Multiple certificates for extension '.cab' defined for CollisionPriorityId ''.
There should be one certificate per extension per collision priority id.
```

**Cause:** PR #35026 added an explicit `.cab` `FileExtensionSignInfo` to
`eng/Signing.props`, but Arcade's built-in `Sign.props` already
registers `.cab` by default:

```xml
<FileExtensionSignInfo Include=".dll;.exe;.mibc;.msi;.cab" CertificateName="Microsoft400" />
```

**Fix:** Remove the duplicate entry. Cab files inside workload MSIs are
still signed with `Microsoft400` via the Arcade default, so no signing
coverage is lost. The `ReconnectModal.razor.js` `FileSignInfo` entry
from #35026 is kept.

### Note on the second fix in #36879

#36879 also restored a missing `MicrosoftWixVersion` property in
`eng/Versions.props`. **That part does not apply to `main`** — `main`
has not taken the WiX 6 migration and still uses `Microsoft.Signed.WiX`
/ `$(MicrosoftSignedWixVersion)` in `eng/NuGetVersions.targets`. There
is no `$(MicrosoftWixVersion)` reference anywhere on `main`, so adding
the property would be dead config.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 515c328a-83aa-4348-9548-4d45f97760c0
<!-- 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

The `find-regression-risk` skill was missing its YAML frontmatter, so
Copilot CLI refused to load it:

```
The following skills failed to load:
* .github/skills/find-regression-risk/SKILL.md: missing or malformed YAML frontmatter
```

Every other `SKILL.md` under `.github/skills/` opens with a `---` block
declaring at least `name` and `description`. This one was the sole
exception, which made the skill invisible to the CLI skill loader — and
to vally's skill linter.

This PR adds a frontmatter block following the conventions used by the
sibling skills (`name`, `description`, `metadata.author`,
`metadata.version`, `compatibility`). The description covers the skill's
purpose, trigger phrases, and "Do NOT use for" guidance, matching the
style of `code-review`, `evaluate-pr-tests`, and `pr-finalize`.

It also refreshes a now-stale comment in
`.github/workflows/skill-validation.yml`. That comment explained why
SKILL.md structural linting is skipped in the eval-spec lint gate,
citing **two** pre-existing failures — the try-fix 500-line overrun and
this missing frontmatter. With the frontmatter fixed, only the try-fix
issue remains, so the comment now reflects reality.

No behavioral change to the skill itself — `Find-RegressionRisks.ps1`
and its tests are untouched.

### Issues Fixed

None filed — reported directly via the Copilot CLI startup error shown
above.

### Validation

Linted with the exact vally version the workflow pins (`VALLY_VERSION:
"0.10.0"`):

```console
$ npx -y @microsoft/vally-cli@0.10.0 lint .github/skills/find-regression-risk
✅ find-regression-risk (2/2 checks passed)

1 skill(s) linted, 1 passed
```

Before the change the skill was not even discovered by the linter. The
frontmatter YAML and the edited workflow YAML were both confirmed to
parse.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: fedc0275-f17d-4af4-af1b-df406fa722a0
Reset patterns:
- global.json
- NuGet.config
- eng/Version.Details.xml
- eng/Versions.props
- eng/common/*
<!-- 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

Adds route template support to Shell navigation, enabling `{param}` path
parameters inspired by ASP.NET Core / Blazor routing. This is **additive
and non-breaking** — existing literal routes work identically, and the
feature is completely dormant unless you register a route containing
`{`.

Fixes #35107

---

## How It Works

### Registration

Register a route with `{param}` segments. Everything inside braces
becomes a path parameter:

```csharp
Routing.RegisterRoute("product/{sku}", typeof(ProductDetailPage));
Routing.RegisterRoute("order/{id:int}", typeof(OrderDetailPage));
Routing.RegisterRoute("review/{stars=5}", typeof(ReviewPage));
```

XAML works too — `{` is safe because XAML only interprets markup
extensions when `{` is the **first character** of the attribute value:

```xml
<ShellContent Route="product/{sku}" ContentTemplate="{DataTemplate local:ProductPage}" />
```

### Navigation

Navigate with values in the path instead of query strings:

```csharp
// Before (query string — still works)
await Shell.Current.GoToAsync("product?sku=seed-tomato");

// After (path parameter)
await Shell.Current.GoToAsync("//products/product/seed-tomato");
```

### Parameter Delivery

Uses existing `[QueryProperty]` and `IQueryAttributable` — **no new
attributes or interfaces needed**:

```csharp
[QueryProperty(nameof(Sku), "sku")]
public class ProductDetailPage : ContentPage
{
    public string Sku { get; set; }  // receives "seed-tomato"
}
```

### Supported Syntax

| Syntax | What it does | Example |
|--------|-------------|---------|
| `{sku}` | Required parameter | `product/{sku}` matches
`product/seed-tomato` |
| `{sku?}` | Optional (must be last) | `product/{sku?}` matches
`product` or `product/seed-tomato` |
| `{stars=5}` | Default value when absent | `review/{stars=5}` → stars
is "5" if you navigate to just `review` |
| `{id:int}` | Constraint — rejects non-matching values |
`order/{id:int}` rejects `order/abc` |
| `{*path}` | Catch-all — captures remaining segments (must be last) |
`files/{*path}` → `docs/report.pdf` |
| `product-{sku}` | Mixed — literal around parameter |
`product-seed-tomato` → sku = "seed-tomato" |
| `{id:int=1}` | Combined constraint + default | Validates when present,
default when absent |

**Constraints:** `int`, `long`, `double`, `bool`, `guid`, `alpha`

### Route Matching Precedence

Literals always win over templates (same as ASP.NET Core). Implemented
via two-pass matching in `FindAndAddSegmentMatch`.

### Path vs Query String

Path parameters take precedence over query strings with the same name.
Both can coexist.

---

## How the Implementation Works

### Route Registration (`Routing.cs`)

When `RegisterRoute` receives a route containing `{`, it parses a
`RouteTemplate` and stores it in a parallel `s_routeTemplates`
dictionary alongside the existing `s_routes` entry.

### Route Matching (`ShellUriHandler.cs`, `RouteRequestBuilder.cs`)

`FindAndAddSegmentMatch` uses a two-pass approach: pass 0 checks literal
routes only (unchanged), pass 1 checks template routes.
`GetNextSegmentMatch` walks template segments in parallel with URI
segments, checking type (literal, parameter, optional, catch-all, mixed)
and applying constraints. The `RouteTemplate` is passed directly from
the caller to handle `CollapsePath` prefix stripping.

### Parameter Delivery (`ShellNavigationManager.cs`)

Path parameters are seeded into `ShellRouteParameters` **before**
`SetQueryStringParameters` (path wins). Route-prefixed keys are also
seeded for intermediate page delivery through Shell's prefix-based
`ApplyQueryAttributes` filtering.

### CurrentState.Location (`ShellSection.cs`,
`ShellNavigationManager.cs`)

Resolved URIs are stored in a separate internal `ResolvedRouteProperty`
on the page. `GetNavigationState` reads `GetResolvedRoute(page) ??
GetRoute(page)`. The page's `Route` keeps the template key for factory
lookups and stack-reuse comparisons.

---

## Migration

**None required.** To opt in, change your route string to include
`{param}`. Everything else stays the same.

---

## Behavior Changes

**None for existing apps.** All new types are `internal`. The two-pass
matching is a no-op for routes without `{`. `CollapsePath` has one new
condition that only triggers for `{`-prefixed segments.

---

## Known Limitations

- **Relative navigation** with template routes not yet supported — use
absolute URIs
- **All-template routes** (no literal prefix) can cause ambiguous
matches
- **Optional/default with collapsed prefix**: navigation succeeds but
defaults may not reach the page via prefix filtering

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!

### Description of Change

Adds a custom-icon API for Maps cluster markers on Android and
iOS/MacCatalyst.

**New public API on `Map`:**
- `ClusterImageProvider` (`Func<ClusterInfo, ImageSource?>?`) — dynamic,
per-cluster icon with highest priority.
- `ClusterImageSource` (bindable `ImageSource?`) — static icon for all
clusters, used when the provider is unset or returns null.
- `ClusterInfo` — read-only context (`Count`, `ClusteringIdentifier`,
`Pins`, `Location`) passed to the provider.

The handler consumes this through the optional
`IMapClusterImageProvider` capability rather than adding a required
member to `IMap`, so existing external `IMap` implementations remain
source-compatible. `ClusterImageVersion` provides a change token for
precise cache invalidation.

**Resolution order:** provider → static source → existing default
bubble. Apps that do not configure either property retain the existing
behavior.

Changing `ClusterImageSource` or `ClusterImageProvider`, including
mutating an existing image source, rebuilds current clusters
immediately. `ClusterImageSource` follows the standard MAUI image
lifecycle: parenting, inherited binding context, `SourceChanged`
updates, and cancellation when replaced.

Both platforms use a bounded LRU cache keyed by stable image content.
Same-key concurrent loads are coalesced into one decode/rasterization,
ordinary pin updates preserve warm entries, and cache invalidation
tracks both the owning map and `ClusterImageVersion`. URI sources honor
`CachingEnabled` and positive `CacheValidity`.

On iOS/MacCatalyst, image-service results and scaled `UIImage` ownership
are disposed deterministically across annotation reuse, uncached loads,
eviction, cleanup, and pooled map reuse.

**iOS bug found and fixed along the way:** on the iOS 26.5/.NET 11
preview 5 bindings, MapKit can hand `GetViewForAnnotation` a cluster
annotation wrapped as a generic `MapKit.MKAnnotationWrapper` instead of
the concrete `MKClusterAnnotation` subclass. The implementation falls
back to `Runtime.GetNSObject<MKClusterAnnotation>(annotation.Handle)`
only when the native object is a cluster annotation, preserving custom
rendering, count glyphs, and cluster selection.

The `ClusteringGallery` sample includes **Custom Cluster Icon
(provider)** and **Static Cluster Icon** actions to exercise both modes.

### What NOT to Do (for future agents)

- Do not add a required `GetClusterImage` member to `IMap`; it breaks
external implementations.
- Do not use a default interface implementation; the Maps projects
target `netstandard2.0`, where it fails with CS8701.
- Do not maintain separate dictionary and FIFO-order structures;
concurrent loads can make them diverge and evict live entries.
- Do not clear all cluster images for ordinary pin collection changes.

#### Testing

- 98 focused `MapTests` pass.
- `Controls.Maps` builds for `netstandard2.0`, `net11.0-android37.0`,
`net11.0-ios26.5`, and `net11.0-maccatalyst26.5`.
- Manually verified by the author on an Android tablet and iPad:
static/provider icons render, update live, and survive re-zoom.

### Issues Fixed

Fixes #36335

> **Note:** targeting `net11.0`, not `main` — pin clustering (#33831)
currently exists on `net11.0`.

---------

Co-authored-by: Kévin Baumeyer <kbaumeyer@divalto.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c7f8afa-6548-4a5c-aa86-946e2db624ef
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
I detected changes in the main branch which have not been merged yet to
net11.0. I'm a robot and am configured to help you automatically keep
net11.0 up to date, so I've opened this PR.

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

* kubaflo
* rmarinho
* PureWeen

## 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.

<img alt="merge button instructions"
src="https://i.imgur.com/GepcNJV.png" width="300" />

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.

``` sh
git fetch
git checkout main
git pull --ff-only
git checkout net11.0
git pull --ff-only
git merge --no-ff main

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

<details>
<summary>or if you are using SSH</summary>

```
git push git@github.com:dotnet/maui HEAD:merge/main-to-net11.0
```

</details>


After PR checks are complete push the branch
```
git push
```

## Instructions for resolving conflicts

:warning: If there are merge conflicts, you will need to resolve them
manually before merging. You can do this [using GitHub][resolve-github]
or using the [command line][resolve-cli].

[resolve-github]:
https://help.github.com/articles/resolving-a-merge-conflict-on-github/
[resolve-cli]:
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

## Instructions for updating this pull request

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

```
git fetch
git checkout -b merge/main-to-net11.0 origin/net11.0
git pull https://github.com/dotnet/maui merge/main-to-net11.0
(make changes)
git commit -m "Updated PR with my changes"
git push https://github.com/dotnet/maui HEAD:merge/main-to-net11.0
```

<details>
    <summary>or if you are using SSH</summary>

```
git fetch
git checkout -b merge/main-to-net11.0 origin/net11.0
git pull git@github.com:dotnet/maui merge/main-to-net11.0
(make changes)
git commit -m "Updated PR with my changes"
git push git@github.com:dotnet/maui HEAD:merge/main-to-net11.0
```

</details>

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.
<!-- 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

This PR improves incremental XAML Hot Reload source generation and
expands deterministic coverage for generator, compilation, and
in-process metadata-update behavior.

- Preserves supported complex properties such as
`CollectionView.ItemTemplate` when an update replaces a root element.
- Buffers diagnostics from speculative source generation so rejected
attempts do not leak or duplicate diagnostics.
- Conservatively emits the existing explicit `skipped (not yet
supported)` marker for inline-resource and `StaticResource`-dependent
complex-property subtrees that cannot be resolved safely in the isolated
speculative context.
- Adds a reusable source-generator Hot Reload harness for strict or
diagnostic-tolerant generation, compilation, live metadata updates,
chained deltas, multiple XAML documents, optional stable C# inputs,
multiple retained instances, and application-host resource/theme
scenarios.
- Reorganizes the larger AI-assisted behavior suites into logical
partial-class files while preserving their fully qualified test names.

### Root Cause and Wave-1 Fix

`UpdateComponentCodeWriter` could create a newly added replacement root,
but it skipped element-valued properties instead of applying the same
value-creation and property-setting pipeline used by
`InitializeComponent`. That silently dropped properties such as
`CollectionView.ItemTemplate` in #36256.

The replacement-root path now speculatively emits supported complex
properties and assigns them to the existing live page. The #36256
coverage verifies both generated source/compilation and a real metadata
update on the same page instance, including a non-null
`CollectionView.ItemTemplate` whose content contains the updated label.

Speculative generation introduced two safety constraints:

- Diagnostics must remain isolated until emission is accepted.
`SourceGenContext` now supports explicit diagnostic buffering, flush,
and discard behavior.
- A fresh speculative context cannot safely resolve ancestor resources
or run the complete resource pipeline. Inline resources and direct,
nested-markup, or element-form `StaticResource` references are therefore
declined explicitly instead of producing a compileable false-success
update that fails or resolves to `null` at runtime.

Only the expected unsupported `InvalidOperationException` falls back to
the skip marker; unexpected exceptions continue to propagate.

#36157 is covered only at the generator boundary: malformed-to-repaired
input recomputes generator diagnostics and the repaired output compiles.
This does not claim IDE Error List, Roslyn edit-session, or `dotnet
watch` recovery. #36156 remains deferred to an IDE/Roslyn host test
because its rude-edit session-poisoning behavior cannot be reproduced
faithfully by a generator unit test.

### Reusable Hot Reload Harness

The harness:

- keeps one incremental generator driver and advances the Roslyn
`EmitBaseline` through successive deltas;
- gives each scenario unique assembly, XAML path, and collectible
`AssemblyLoadContext` identities;
- supports generation-only, compile-only, and full live-update paths;
- supports diagnostic-tolerant versions, multiple XAML documents,
optional stable C# sources, and multiple retained roots;
- uses metadata-aware fact and theory attributes so live-update tests
skip, rather than fail, when the runtime does not support
`MetadataUpdater.ApplyUpdate`;
- resets `XamlHotReloadState`, restores `Application.Current`,
unregisters roots from `XamlComponentRegistry`, disposes
metadata/streams, and unloads the collectible context.

Generated `x:Name` fields still require manual C# stubs because
`CodeBehindCodeWriter` is outside this harness.

### Wave-2 Coverage

The living AI-assisted index accounts for 55 test methods across 35
behavior IDs/capabilities covering:

- dynamic and merged resources, styles, themes, and application
resources;
- visual states and behaviors;
- data/control templates, selectors, compiled bindings, and
`BindableLayout`;
- bindings, markup extensions, and `MultiBinding`;
- nested generated controls and namescopes;
- multi-document and cross-assembly generator invalidation.

The metadata-enabled AI-assisted run reports **41 passed, 18
intentionally skipped, and 0 failed**. Theory rows affect the reported
case count.

Passing tests are classified as live, construction, generator/compile
guards, or explicit decline guards. Each skip-gated RED-PROBE names a
nearby executable passing guard. The 18 skipped probes encode desired
behavior for known gaps; they are not claimed as passing runtime
coverage.

The larger resource/theme, visual-state, template, binding/markup, and
nested-control suites are split into behavior-named partial files for
reviewability without changing xUnit discovery, attributes, fixtures, or
method identities.

### Known Limitations and Deferred Lanes

- A compiled `ResourceDictionary Source=` payload is unavailable in the
in-memory collectible load context. Multi-document and `Source=` tests
therefore verify tracking, generation, and compilation; their live
payload probes remain skip-gated.
- Cross-assembly tests cover incremental-generator reference
invalidation and caching only. Applying deltas to a separately loaded
runtime assembly remains an integration lane.
- IDE/Hot Reload host behavior, Roslyn rude-edit recovery, `dotnet
watch`, devices, native handlers, rendered output, and lifecycle
behavior remain integration/host lanes.
- The AppThemeBinding live probe remains skip-gated because the current
update writer supplies an `IProvideValueTarget` with a null
`TargetProperty`; its passing guard proves generated branch capture
only.
- Future keyed-template and selector factories remain tracked by #36482.
Passing construction/source guards do not prove post-update future
realization.
- Complex-property and collection reconciliation remains tracked by
#36732. Explicit decline guards prove that unsupported updates are
skipped and compile, not that live reconciliation succeeds.

### What NOT to Do

- Do not send speculative visitor diagnostics directly to the production
diagnostic sink; rejected attempts must discard them.
- Do not emit resource-dependent subtrees from an isolated context and
treat successful compilation as proof of runtime resolution.
- Do not catch broad exceptions and silently degrade unexpected
generator failures.
- Do not use generated-source markers as evidence of live runtime
behavior.
- Do not treat generator-only recovery coverage as proof of IDE or
`dotnet watch` recovery.

### Issues Fixed

Fixes #36256

Related coverage and roadmap issues:

- #36157: generator diagnostic recomputation coverage only; host
recovery is not fixed here.
- #36156: deferred IDE/Roslyn host scenario.
- #36482: future template/selector factory roadmap; not fixed by this
PR.
- #36732: complex-property and collection reconciliation roadmap; not
fixed by this PR.

### Test Coverage

```bash
DOTNET_MODIFIABLE_ASSEMBLIES=debug dotnet test src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj -c Debug
DOTNET_MODIFIABLE_ASSEMBLIES=debug dotnet test src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj -c Release
env -u DOTNET_MODIFIABLE_ASSEMBLIES dotnet test src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj -c Debug
```

- `SourceGen.UnitTests` Debug: **497 passed / 18 skipped / 0 failed**
(515 total).
- `SourceGen.UnitTests` Release: **497 passed / 18 skipped / 0 failed**
(515 total).
- `XamlIncrementalHotReloadE2ETests`: **13 passed / 0 skipped / 0
failed**.
- `HotReload.AiAssisted`: **41 passed / 18 skipped / 0 failed**.
- Default Debug with metadata updates explicitly unavailable: **475
passed / 37 skipped / 0 failed** (512 total). xUnit reports each
skip-gated theory once rather than once per data row.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b9bf3f3-3e24-49bf-b3eb-c075858ee563
Copilot-Session: 8dc5778b-13c3-40aa-8b21-76617ea71b69
Copilot-Session: f093ec6b-e912-40c6-acae-f308f79ee558
Copilot-Session: 8191a632-a704-4949-865b-a38bd8133f6d
Copilot-Session: 96ebbad1-0079-4d43-a464-bb0b9ebadd89
Copilot-Session: d5e424fa-b2af-4909-9a4d-3b2114ac147d
Copilot-Session: ba10e73c-e9b1-46c7-8bf6-c7cd0a2fa15c
Copilot-Session: 3954ca4a-026e-46b1-a878-8ed0ba5224be
Copilot-Session: 3aecbe3b-4302-428f-a397-9f0923d19656
Copilot-Session: 60c67cff-beec-4a4b-848d-fafbe39b837b
Copilot-Session: 53ff611b-9d3e-4671-8950-c2c0c3e93d64
…6970)

This PR removes `Controls.Sample.Sandbox` changes that were
unintentionally bundled with the route-template work, so only the
intended feature code remains in the original stream. The Sandbox sample
is restored to its prior baseline behavior.

- **Scope correction**
- Reverts Sandbox-only edits that were part of the earlier PR payload
but not part of the intended deliverable.

- **Sandbox app restoration**
  - Restores previous startup mode and Shell layout in:
    - `App.xaml.cs`
    - `SandboxShell.xaml`
    - `SandboxShell.xaml.cs`
    - `MainPage.xaml.cs`

- **Removal of unintended sample artifacts**
- Removes route-template demo pages that should not have shipped in this
change set:
    - `ProductPage.*`
    - `ReviewPage.*`
    - `OrdersPage.*`
    - `OrderDetailPage.*`

```csharp
// Restored baseline startup behavior in Sandbox
bool useShell = false;
```

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sheiksyedm <23059975+sheiksyedm@users.noreply.github.com>
…ompile filtering (#36957)

<!-- 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

This focused follow-up addresses two empirically validated gaps found by
the GPT-5.6 Sol post-merge verification of #36654.

1. `BackendIdentity` now defaults `ActivationValue` even when
`TargetPlatformIdentifier` or `TargetPlatformIdentifiers` is also
present. A single registration can therefore activate through a
recognized TPI or through `MauiActiveBackend` on a neutral TFM, while
explicit `ActivationValue` and `ActivationProperty` metadata still win.
2. platform Compile removal now starts from the `Compile` items in the
`ExcludeFromCurrentConfiguration=true` metadata batch and intersects
them with physical `Platforms/**` candidates. A fresh filesystem glob
can no longer pull an explicitly false Compile item from another
metadata bucket into the removal set. The helper-item removal pattern
remains in place, preserving active item order and avoiding
remove/re-add duplication.

## Before and After

Before this change, a registration such as:

```xml
<MauiPlatformSpecificFolder Include="Platforms/MacOS/" TargetPlatformIdentifiers="macos" BackendIdentity="macos" />
```

worked for recognized TPI `macos` but did not activate on a neutral TFM
with `MauiActiveBackend=macos`. It now supports both paths and remains
inactive for another recognized TPI or a mismatched backend.

Before this change, the presence of any true Compile metadata batch
caused a fresh `Platforms/**` glob to include physical files explicitly
marked false by a downstream target. Removal is now constrained to the
actual true Compile identities under the platform folder.

## Tests

The real shipping SingleProject targets are covered by regressions for:

- one dual-path macOS registration through recognized TPI and neutral
backend activation, plus recognized-TPI and backend mismatch negatives;
- two physical platform Compile files in different metadata buckets with
no folder allow-list, asserting only the true item is removed and the
surviving list is ordered and duplicate-free.

Validation:

- complete `MSBuildTests.SingleProject_*` matrix: **46 passed, 0
failed**;
- new regression matrix: **7 passed, 0 failed**;
- `Controls.Build.Tasks.csproj` build: **succeeded with 0 warnings and 0
errors**;
- targeted `dotnet format`: completed successfully.

The unfiltered local graph is unavailable on this Mac because the
platform project graph requires the iOS workload (`NETSDK1147`) and the
full BuildTasks solution filter includes .NET Framework 4.7.2 projects
without local reference assemblies (`MSB3644`). The workload-neutral
matrix above used the repository-pinned .NET 11 SDK with platform TFMs
disabled and imported the exact shipping targets.

### Candidate selection and final review

#36957 is the selected implementation. Alternatives #36955 and #36956
both fail their own new Windows Helix XAML regression by removing the
explicit-false Compile item. This branch uses FullPath/PathLike
intersection, passes the expanded 46-case matrix, preserves metadata and
duplicate count, handles absolute Compile identities, and skips the
platform filesystem glob when no removal batch exists.

Neutral activation of built-in backend identities is intentional: #36654
documented that built-ins use the same registration shape and that
ActivationValue defaults from BackendIdentity. A dedicated regression
now locks that contract.

## Issues Fixed

Part of #34099
Part of #35021
Fixes #36650
Follow-up to #36654

---------

Co-authored-by: PureWeen <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ac6265fe-09a0-473c-b3f9-9ec6d6dd97cd
Copilot-Session: 66f84348-6476-4097-8b7f-f240338e85c3
…ntent property changes at runtime (#36902)

<!-- 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!

**Faiilure Test on android hanlder path** :
_**ShellContentShouldUpdateWhenContentPropertyChanges**_

This pull request introduces significant improvements to how
`ShellSectionHandler` on Android manages and updates its `ShellContent`
items, especially in response to property changes and collection
modifications. The main goals are to ensure proper event subscription
management, keep the UI in sync when content changes, and make adapter
updates more robust.

The property-change tracking and invalidation approach added here
mirrors what was already implemented for the legacy renderer in
[#34630](#34630), bringing the same
`ShellContent.PropertyChanged` subscription/invalidation pattern to the
new handler-based Android Shell architecture, since the handler
previously had no equivalent logic and silently ignored `Content`
changes at runtime.

**ShellContent property change tracking and adapter updates:**

* Added tracking of currently-subscribed `ShellContent` items via a
`_subscribedItems` list, ensuring that `PropertyChanged` events are
always wired/unwired correctly as items are added/removed.
[[1]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R47)
[[2]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R205-R211)
[[3]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R439-R446)
[[4]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R522-R597)
* Implemented `OnShellContentPropertyChanged` to handle updates when a
`ShellContent`'s content changes, including invalidating the adapter and
syncing the toolbar state if the active tab is affected.
* Added `UpdateContentPropertyChangedSubscriptions` to efficiently
update event subscriptions in response to collection changes, including
handling collection resets, additions, and removals.

**Adapter robustness and notification improvements:**

* Introduced `InvalidateShellContent` and `SafeNotifyDataSetChanged`
methods to the adapter, ensuring that UI updates are safely triggered
even if `ViewPager2` is in a layout pass, and logging a warning if
updates get stuck.
* Replaced direct calls to `NotifyDataSetChanged` with the safer
`SafeNotifyDataSetChanged` throughout the handler, reducing the risk of
UI inconsistencies or crashes.
[[1]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R510-R513)
[[2]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144L531-R623)
[[3]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R829-R864)

**Other improvements:**

* Added missing `using` directives for required types such as
`System.ComponentModel`, `Microsoft.Extensions.Logging`, and
`Microsoft.Maui.Platform`.
[[1]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R5)
[[2]](diffhunk://#diff-46fc3573f39a6e0c764825dc5fac89c15fa741e4eb17cdc979aca5ed2acba144R16-R20)

These changes collectively make tab content updates more reliable and
maintainable, especially when dynamic changes occur in the
`ShellSection`, and bring the handler-based Android Shell in line with
the equivalent renderer-based fix already merged in
[#34630](#34630).

### Why no tests added : 

- No new automated test was added in this PR because the existing UI
test `ShellContentShouldUpdateWhenContentPropertyChanges`  already
covers this behavior — it was the test that started failing in net11 CI,
which is what prompted this fix. Rather than adding a new test, this PR
restores the passing behavior of that existing test

<!-- 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 #36809 

### Tested the behavior in the following platforms

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



| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/cdcb02d6-a663-47fc-a85d-2e1143198070">
| <video
src="https://github.com/user-attachments/assets/04e05f85-9b78-4a56-8503-76b1e5fe7b1a">
|

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
This PR addresses UI test failures in the Net11 branch and includes
updates to improve rendering and test stability across platforms.

- The
**BottomSheetDetentHeightIsCorrectWhenCollectionViewIsMeasuredBeforeMount**
test passed locally in both CV1 and CV2. However, in CI, it fails in CV1
but passes in CV2. To avoid flaky issues, the sample was changed to use
CollectionView2.
Reset patterns:
- global.json
- NuGet.config
- eng/Version.Details.xml
- eng/Versions.props
- eng/common/*
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

<!-- 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

Auto-approve and enable GitHub native auto-merge for immutable snapshots
of these exact forward-merge targets:

```text
main    => net11.0
net11.0 => release/11.0.1xx-preview7
net11.0 => release/11.0.1xx-rc1
net11.0 => release/11.0.1xx-rc2
```

### Immutable snapshot design

Each caller workflow checks for its generated merge PR before invoking
Arcade:

```text
no open merge PR  -> run Arcade and create a fresh snapshot
open merge PR     -> leave its branch unchanged while CI runs
```

The checks use exact head/base pairs and require the PR authoring App to
be `github-actions` with `isCrossRepository == false`. The release
workflow resolves the current `MergeToBranch` from
`github-merge-flow-release-11.jsonc` on `net11.0`, and passes
`configuration_file_branch: net11.0` to Arcade so the gate and merge
implementation use the same source of truth.

Workflow runs are serialized with distinct concurrency groups so
simultaneous push/schedule/manual runs cannot both pass the check and
create or update the same PR. Because scheduled workflows start from the
default branch, the release schedule uses a schedule-only job to
dispatch `merge-net11-to-release.yml` at ref `net11.0`; the dispatched
run is not a schedule event and cannot recurse.

During rollout, the schedule job first compares the parsed
safety-critical sections (`concurrency`, `CheckForOpenMergePullRequest`,
and `Merge`) between the workflow on `main` and `net11.0`. It skips the
dispatch until the full immutable-snapshot gate has propagated, while
allowing unrelated branch-specific workflow differences. Fetch or parse
failures fail visibly instead of dispatching an unknown definition.

The read-only snapshot checks use read-only `GITHUB_TOKEN` permissions.
Only the reusable Arcade merge job retains content and pull-request
write access.

New source commits that arrive while a merge PR is open wait for the
next generated PR. Once the current PR merges or closes, the next push
or daily schedule creates a fresh snapshot containing the remaining
commits.

This intentionally stops using Arcade's existing "fast-forward the open
merge PR" behavior. The generated PR head does not change during CI, so
source-branch pushes do not invalidate its approval or restart CI.

### Policy Service rule

The rule runs only on `Opened`; `Synchronize` is not accepted.

It requires:

- event sender `github-actions[bot]`
- event sender is also the PR author
- exact target branch
- exact, fully anchored generated title

Human conflict-resolution pushes do not trigger reapproval.
Bot-attributed `/rebase` synchronization also does not trigger the
policy, closing the review-bypass path identified in the adversarial
review.

### Review behavior and accepted limitation

`MAUI protection` intentionally remains:

```text
dismiss_stale_reviews_on_push: true
require_last_push_approval: false
required_approving_review_count: 1
```

This preserves the repository's human-review workflow: a maintainer who
pushes a fix to another person's PR can provide the subsequent approval
without requiring a third reviewer. This PR does not modify repository
rulesets or add a bypass.

The generated merge PR remains safe under these settings. Policy Service
approves only the initial `Opened` snapshot, the caller workflow refuses
to invoke Arcade while the exact bot-authored PR remains open, and any
out-of-band head push dismisses the approval with no automatic
reapproval path.

Ordinary target-branch advancement does not require the generated PR to
update because the required status-check rules use
`strict_required_status_checks_policy: false`. If the immutable head
remains conflict-free, its approval remains valid, and required checks
pass, auto-merge can complete against the advanced base. In the narrower
case where base activity actually changes the reviewed diff or merge
base, GitHub can dismiss the approval and safely stall the PR. That
fail-closed limitation is accepted for this automation.

### Exact branch and title allow-list

```text
net11.0                    + ^[automated] Merge branch 'main' => 'net11.0'$
release/...-preview7       + ^[automated] Merge branch 'net11.0' => 'release/...-preview7'$
release/...-rc1            + ^[automated] Merge branch 'net11.0' => 'release/...-rc1'$
release/...-rc2            + ^[automated] Merge branch 'net11.0' => 'release/...-rc2'$
```

Each entry in the file contains the full literal branch and anchored
regex. Targets outside this allow-list remain manual.

### Merge behavior

```yaml
- enableAutoMerge:
    mergeMethod: merge
```

This always creates a true merge commit, never squash or rebase. Arcade
relies on merge ancestry to determine what remains to flow.

GitHub completes auto-merge only when the PR has no merge conflict and
required checks pass.

### Required checks

| ruleset | checks | Policy Service bypass |
| --- | --- | --- |
| `MAUI required CI checks` | `maui-pr` | **none** |
| `MAUI device and UI test checks` | `maui-pr-devicetests`,
`maui-pr-uitests` | pull requests only |

A failing or pending `maui-pr` blocks the merge. Device/UI checks do
not.

`MAUI protection` has no Policy Service bypass. It requires one ordinary
approval; Policy Service supplies it for the exact authenticated
`Opened` events above.

### CODEOWNERS

PR #36890 removes the invalid CODEOWNERS file. `Require review from Code
Owners` is disabled in `MAUI protection`; the ordinary one-approval
requirement remains.

### Accepted trust boundary

An initial `Opened` event authorizes on exact title/base plus
`github-actions[bot]` as both sender and PR author. A collaborator with
repository push access could deliberately create a same-repository
workflow and matching PR. Real `maui-pr` from Azure Pipelines
integration 9426 must still pass, but there is no additional human
review under the intentionally ordinary one-review policy.

This tradeoff is accepted for these exact forward-merge target pairs.
The immutable-snapshot gate prevents later human content from being
reapproved through synchronization. No new App is installed and no
bypass is added to `MAUI protection` or the `maui-pr` ruleset.

### Verification

- Both caller workflows pass `actionlint`.
- All three changed YAML files parse successfully.
- The live target resolver returns `release/11.0.1xx-preview7`.
- Exact App/head/base/same-repository queries identify #36886 (`main =>
net11.0`) and #36880 (`net11.0 => release/11.0.1xx-preview7`).
- The semantic rollout check rejects the current old `net11.0` workflow
and accepts matching safety-critical sections.
- Official GitHub documentation confirms that `workflow_dispatch` events
created with `GITHUB_TOKEN` start workflow runs; the dispatched event
skips the schedule-only job.
- The Policy Service file parses and GitOps schema validation runs on
every update.
- The live `MAUI protection` settings and effective non-strict
required-status-check rules were reverified on 2026-07-31.

### Issues Fixed

None; infrastructure automation.

---------

Co-authored-by: PureWeen <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b2b2dd6-bf5f-4179-8a8f-c4c85b9bce26
@PureWeen
PureWeen enabled auto-merge July 31, 2026 16:45
PureWeen
PureWeen previously approved these changes Jul 31, 2026
pictos and others added 2 commits July 31, 2026 19:17
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

<!-- 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 #35302

### Description of Change
This pull request introduces a new caching mechanism for
`ImmutableBrush` instances, specifically optimizing color-to-brush
conversions in the `Brush` class. It adds a two-stage cache (simple and
LRU) to reduce allocations and improve performance when repeatedly
converting colors to brushes. Additionally, a suite of benchmarks is
included to measure the impact of these changes on property-change
propagation in common controls.

**Caching improvements for brush creation:**

* Introduced a new `CacheWithSwitch` class that provides a two-stage
caching strategy for `ImmutableBrush` instances keyed by `Color`. It
starts with a simple dictionary cache and automatically promotes to an
LRU cache when capacity is reached, reducing memory allocations and
improving brush reuse.
(`src/Controls/src/Core/Internals/CacheWithSwitch.cs`)
* Added an `ICache<TKey, TValue>` interface to standardize cache
implementations used for brush caching.
(`src/Controls/src/Core/Internals/ICache.cs`)
* Implemented an `LRUBrushCache` class for least-recently-used caching
of brushes, used as the second stage of `CacheWithSwitch`.
(`src/Controls/src/Core/Internals/LRUBrushCache.cs`)

**Integration with Brush class:**

* Updated the `Brush` class to use the new cache for implicit
conversions from `Color` and `SolidPaint`, ensuring brush instances are
reused whenever possible. (`src/Controls/src/Core/Brush/Brush.cs`)
[[1]](diffhunk://#diff-383e75280c95c1ee1bf2545184c1c002f647d95eacae4b3230bf2c2a2461f138R2)
[[2]](diffhunk://#diff-383e75280c95c1ee1bf2545184c1c002f647d95eacae4b3230bf2c2a2461f138R15-R23)
[[3]](diffhunk://#diff-383e75280c95c1ee1bf2545184c1c002f647d95eacae4b3230bf2c2a2461f138L103-R109)

**Benchmarking and performance validation:**

* Added a new benchmark suite to measure property-change propagation
performance and allocations for `Label`, `Button`, and `Entry` controls,
with a focus on background color changes that exercise the new brush
caching logic.
(`src/Core/tests/Benchmarks/Benchmarks/PropertyChangePropagationBenchmarker.cs`)


## Brush cache benchmark: branch vs `main`

**Setup:** `main` has no brush cache — every `Paint → Brush` conversion
allocates `new SolidColorBrush { Color = c }`. This branch adds
`Lru64ColorVectorInlineBrushCache` (inline-array + SIMD lookup) and
wires it into `Brush.cs`. Benchmarked over identical color sets,
ShortRun, Apple M4 Max.

> **Caveat:** `main` targets net10 (ran on .NET 10.0.9) and this branch
targets net11 (ran on .NET 11.0-preview.6) — the runtimes differ because
the TFMs differ. As a control, the branch `NullCache`
(allocate-every-time, ~68 ns / 1024 B) closely matches main's no-cache
(~84 ns / 1116 B), so the runtime gap is small (~15 ns) and the cache
wins are real.

### Production path — `InlineLruCache` (branch) vs no-cache (`main`)

| Scenario | main (no cache) | branch InlineLruCache | Time Δ | main
alloc | branch alloc | Alloc Δ |
|---|---|---|---|---|---|---|
| 40 colors (fits in cap 50) | 84.36 ns | **16.92 ns** | **≈5.0× faster
(−80%)** | 1116 B | **105 B** | **−90.6%** |
| Weighted (20 hot ×10 + 40 cold) | 80.53 ns | **24.88 ns** | **≈3.2×
faster (−69%)** | 1116 B | **180 B** | **−83.9%** |
| 60 colors (> cap 50, thrashes) | 84.24 ns | 87.06 ns | ≈even (+3%) |
1116 B | 1024 B | −8% |

### Full branch run (net11, ShortRun)

| Scenario | LruCache (dict+LL) | InlineLruCache (new) | NullCache
(≈main) |
|---|---|---|---|
| 40 colors | 36.87 ns / 119 B | **16.92 ns / 105 B** | 68.19 ns / 1024
B |
| 60 colors | 137.85 ns / 1.05 KB | **87.06 ns / 1 KB** | 75.61 ns / 1
KB |
| Weighted | 36.77 ns / 190 B | **24.88 ns / 180 B** | 68.02 ns / 1024 B
|

### Takeaways

- **vs main:** for realistic workloads (colors fit in the cap), the new
cache is **3–5× faster and allocates ~6–11× less** — main allocates a
full `SolidColorBrush` (~1 KB) on every conversion, the cache returns a
shared instance.
- **vs the old LRU in this PR:** InlineLruCache is also **1.5–2.1×
faster** than the dict+linked-list `LRUBrushCache`.
- **The 60-color row is pathological:** 60 distinct colors exceed the
capacity-50 benchmark, so it thrashes (every access misses + allocates).
In production the cap is 64 and typical apps reuse a handful of colors,
so the 40-color / weighted rows are representative.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Resolve release SDK and dependency alignment conflicts by preserving the Preview 7 branch pins.

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

Copilot-Session: 3b38a29c-edf8-4e9a-a247-e270e643cc54
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Use a test-specific NuGet configuration that permits only Avalonia.Controls.Maui packages from NuGet.org while retaining the existing approved feeds for the rest of the dependency graph.

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

Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Keep NuGet.org restricted by package-source mapping while including the Avalonia transitive dependency graph required by the template build.

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

Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

Include the non-Avalonia-named MicroCom runtime dependency in the test-only NuGet.org package-source mapping while keeping all other packages on approved feeds.

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

Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@kubaflo

kubaflo commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Prevent the MainThread bridge and dispatcher tests from clearing their shared process-global DispatcherProvider state while another test is running.

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

Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
@kubaflo

kubaflo commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@PureWeen
PureWeen enabled auto-merge August 3, 2026 13:14
@PureWeen
PureWeen disabled auto-merge August 3, 2026 13:17
@PureWeen
PureWeen merged commit fc682df into release/11.0.1xx-preview7 Aug 3, 2026
43 checks passed
@PureWeen
PureWeen deleted the merge/net11.0-to-release/11.0.1xx-preview7 branch August 3, 2026 13:18
@github-actions github-actions Bot added this to the .NET 11.0-preview7 milestone Aug 3, 2026
PureWeen pushed a commit that referenced this pull request Aug 3, 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

Flows the remaining CI fixes discovered while validating the automated
`net11.0` to Preview 7 merge in #36986 back to `net11.0`.

- Adds the missing iOS hosting namespace so the TabbedPage device tests
compile.
- Makes Avalonia template tests skip template post-action restore and
use a test-specific NuGet configuration. Existing approved feeds remain
mapped to all packages; NuGet.org is limited to the external `Avalonia*`
and `MicroCom.*` dependency families.
- Serializes `DispatcherTests` and `MainThreadBridgeTests`, which both
mutate the process-global `DispatcherProvider`, preventing the Helix
race observed in build 1536641.

The modal device-test override fix was removed from this PR after it
landed independently in #37030.

These remaining fixes produced a successful aggregate `maui-pr` run for
#36986 in [build
1536659](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1536659).

The source-only version-property merge hardening remains separately
tracked by #37019.

## Testing

- `Core.UnitTests`: 22 targeted `DispatcherTests` and
`MainThreadBridgeTests` passed on .NET 11 RC1 after rebasing.
- iOS device-test compilation was validated while fixing #36986.
- Avalonia integration scenarios restored through the restricted
package-source mapping in successful `maui-pr` build 1536659.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Vally Fixture <vally-fixture@example.invalid>
Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
Vignesh-SF3580 pushed a commit to Vignesh-SF3580/maui that referenced this pull request Aug 10, 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

Flows the remaining CI fixes discovered while validating the automated
`net11.0` to Preview 7 merge in dotnet#36986 back to `net11.0`.

- Adds the missing iOS hosting namespace so the TabbedPage device tests
compile.
- Makes Avalonia template tests skip template post-action restore and
use a test-specific NuGet configuration. Existing approved feeds remain
mapped to all packages; NuGet.org is limited to the external `Avalonia*`
and `MicroCom.*` dependency families.
- Serializes `DispatcherTests` and `MainThreadBridgeTests`, which both
mutate the process-global `DispatcherProvider`, preventing the Helix
race observed in build 1536641.

The modal device-test override fix was removed from this PR after it
landed independently in dotnet#37030.

These remaining fixes produced a successful aggregate `maui-pr` run for
dotnet#36986 in [build
1536659](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1536659).

The source-only version-property merge hardening remains separately
tracked by dotnet#37019.

## Testing

- `Core.UnitTests`: 22 targeted `DispatcherTests` and
`MainThreadBridgeTests` passed on .NET 11 RC1 after rebasing.
- iOS device-test compilation was validated while fixing dotnet#36986.
- Avalonia integration scenarios restored through the restricted
package-source mapping in successful `maui-pr` build 1536659.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Vally Fixture <vally-fixture@example.invalid>
Copilot-Session: 37faae15-0e4c-46fd-9bef-f3006c8aaee8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.