Skip to content

[automated] Merge branch 'main' => 'net11.0' - #36953

Merged
kubaflo merged 4 commits into
net11.0from
merge/main-to-net11.0
Jul 30, 2026
Merged

[automated] Merge branch 'main' => 'net11.0'#36953
kubaflo merged 4 commits into
net11.0from
merge/main-to-net11.0

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

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.

merge button instructions

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

Instructions for merging via command line

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

git fetch
git checkout main
git pull --ff-only
git checkout 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
or if you are using SSH
git push git@github.com:dotnet/maui HEAD:merge/main-to-net11.0

After PR checks are complete push the branch

git push

Instructions for resolving conflicts

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

Instructions for updating this pull request

Contributors to this repo have permission update this pull request by pushing to the branch 'merge/main-to-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
or if you are using SSH
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

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.

PureWeen and others added 4 commits July 30, 2026 15:20
<!-- 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/*
@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.

@kubaflo
kubaflo merged commit d07c3b2 into net11.0 Jul 30, 2026
29 checks passed
@kubaflo
kubaflo deleted the merge/main-to-net11.0 branch July 30, 2026 21:56
@github-actions github-actions Bot added this to the .NET 11.0-preview7 milestone Jul 30, 2026
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.

3 participants