Skip to content

Add winapp-maui skill for the MAUI resizetizer manifest dependency#610

Open
pictos wants to merge 3 commits into
microsoft:mainfrom
pictos:add-maui-resizetizer-skill
Open

Add winapp-maui skill for the MAUI resizetizer manifest dependency#610
pictos wants to merge 3 commits into
microsoft:mainfrom
pictos:add-maui-resizetizer-skill

Conversation

@pictos

@pictos pictos commented Jul 9, 2026

Copy link
Copy Markdown

Summary

Adds a dedicated winapp-maui skill that documents how to package and sign .NET MAUI Windows apps with winapp, focused on solving the resizetizer manifest dependency.

The problem it solves

A .NET MAUI project ships a source manifest at Platforms/Windows/Package.appxmanifest full of MAUI-specific $placeholder$ tokens (DisplayName, Logo, Identity Name/Publisher/Version, tile/splash logos). winapp package only auto-resolves its own $targetnametoken$/$targetentrypoint$ tokens — it does not understand MAUI's $placeholder$ tokens, so pointing it at the source manifest fails with:

manifest contains unresolved placeholders: $placeholder$

MAUI's resizetizer (bundled with the MAUI workload) fills those tokens at build/publish time into generated manifests:

  • obj\<Config>\<TFM>\<RID>\resizetizer\m\Package.appxmanifest (MAUI tokens resolved; entry-point tokens remain, resolved by --executable)
  • bin\<Config>\<TFM>\<RID>\AppxManifest.xml (fully resolved)

The fix is to point winapp package --manifest at the generated manifest, never the source one — and never hand-edit the source manifest (the resizetizer overwrites its generated copy each build).

What's included

  • New skill fragment docs/fragments/skills/winapp-cli/maui.md and generated SKILL.md in .github/plugin/skills/winapp-cli/maui/ and .claude/skills/winapp-maui/. Covers: root cause, where the resolved manifest lives, publish→pack→sign workflow, publisher/cert matching, a full GitHub Actions CI example (x64 + arm64, self-contained), tips, and a troubleshooting table.
  • Registered maui in scripts/generate-llm-docs.ps1 ($SkillNames, $SkillDescriptions, $SkillCommandMap = empty — links to guidance, like frameworks) and in scripts/validate-llm-docs.ps1.
  • Cross-links from winapp-frameworks (guides table row + ### .NET MAUI note + related-skills bullet) and winapp-troubleshoot (error-table row + related-skills bullet).

Validation

  • Generated SKILL.md files verified byte-identical to generate-llm-docs.ps1 output (ignoring the version line, which the release build stamps).
  • .claude/skills/winapp-maui/SKILL.md verified byte-identical to the plugin source (what sync-claude-plugin.ps1 produces).
  • Guidance validated end-to-end against a real MAUI app (LogViewer) with WinAppCLI 0.4.0: reproduced the placeholder failure, then produced a signed MSIX with 0 unresolved placeholders by pointing --manifest at the resizetizer manifest.

.NET MAUI's checked-in Platforms/Windows/Package.appxmanifest contains
$placeholder$ tokens that winapp package does not resolve. MAUI's
resizetizer fills them at build/publish time into a generated manifest.
This adds a dedicated winapp-maui skill documenting how to point winapp
at the resolved manifest (obj/.../resizetizer/m/Package.appxmanifest or
bin/.../<RID>/AppxManifest.xml), plus publish/sign/CI workflows.

- New fragment docs/fragments/skills/winapp-cli/maui.md and generated
  SKILL.md in .github/plugin and .claude
- Register maui in generate-llm-docs.ps1 and validate-llm-docs.ps1
- Cross-link the new skill from winapp-frameworks and winapp-troubleshoot

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 19:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new dedicated Copilot/Claude agent skill, winapp-maui, documenting how to package and sign .NET MAUI Windows apps with winapp. Its central purpose is to explain the "resizetizer manifest dependency": MAUI's source Platforms/Windows/Package.appxmanifest is full of $placeholder$ tokens that winapp package does not resolve, so users must point --manifest at the resizetizer-generated manifest instead. The skill fits into the repo's auto-generated docs pipeline (fragment → plugin SKILL.md.claude mirror) and cross-links into the existing winapp-frameworks and winapp-troubleshoot skills.

Changes:

  • Adds the maui.md skill fragment plus its generated SKILL.md in .github/plugin/skills/winapp-cli/maui/ and .claude/skills/winapp-maui/.
  • Registers maui in the doc-generation and validation scripts (generate-llm-docs.ps1, validate-llm-docs.ps1).
  • Adds cross-links (frameworks table row + .NET MAUI section, troubleshoot error-table row, related-skills bullets) across the frameworks/troubleshoot fragments and their generated mirrors.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
docs/fragments/skills/winapp-cli/maui.md New hand-written skill fragment: root cause, manifest locations, publish→pack→sign workflow, CI example, troubleshooting.
.github/plugin/skills/winapp-cli/maui/SKILL.md Generated Copilot plugin skill (frontmatter + fragment body); verified identical to fragment.
.claude/skills/winapp-maui/SKILL.md Claude mirror of the plugin skill; verified byte-identical to the plugin SKILL.md.
scripts/generate-llm-docs.ps1 Registers maui in $SkillNames, $SkillDescriptions, and $SkillCommandMap (empty, like frameworks).
scripts/validate-llm-docs.ps1 Adds maui to the skill-drift validation list.
docs/fragments/skills/winapp-cli/frameworks.md Adds a .NET MAUI table row/section and a related-skills link to winapp-maui.
.github/plugin/skills/winapp-cli/frameworks/SKILL.md Generated mirror of the frameworks fragment changes.
.claude/skills/winapp-frameworks/SKILL.md Claude mirror of the frameworks changes.
docs/fragments/skills/winapp-cli/troubleshoot.md Adds a MAUI placeholder-error row and related-skills link.
.github/plugin/skills/winapp-cli/troubleshoot/SKILL.md Generated mirror of the troubleshoot changes.
.claude/skills/winapp-troubleshoot/SKILL.md Claude mirror of the troubleshoot changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nmetulev nmetulev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI-generated PR review

This review was produced by an automated multi-dimensional review agent (GitHub Copilot CLI) with a second-model cross-check. Everything below is a suggestion, not a mandate — the author decides what to implement, defer, or dismiss. Nothing here blocks merge, and any individual item may be wrong or simply not worth the churn. Specific items are attached as inline comments.

Verdict

Solid, well-written skill. I built the CLI and ran scripts/validate-llm-docs.ps1exit 0: the maui skill regenerates with zero drift, and the .github/plugin and .claude mirrors are byte-identical to the fragment. 0 critical · 0 high · 4 medium · 2 low.

Finding not tied to a diff line

M2 · llms.txt (lines 16-24) · docs sync — medium. The hand-maintained "Copilot Plugin Skills" list enumerates every skill but omits the new maui/SKILL.md, and no script regenerates llms.txt, so it won't self-heal. Suggestion: add a maui/SKILL.md entry between the frameworks and ui-automation lines.

Inline comments (author's discretion)

  • M1 maui.md — the "preferred" bin\…\AppxManifest.xml + the no---manifest shortcut don't hold for the WindowsPackageType=None flow the skill documents (medium; originally high, downgraded on cross-check).
  • M3 frameworks.md — standalone winapp-maui skill vs the frameworks+guide convention (medium, design call).
  • M4 validate-llm-docs.ps1 — pre-existing: validate list omits ui-automation (medium).
  • L1 / L2 maui.md — CI cert-cleanup and password-handling nits (low).

Verified clean

CLI UX — every command/flag in the skill matches cli-schema.json (package--cert/--cert-password; sign → positional cert + --password; cert generate --manifest). Plugin generation pipeline — both mirrors generate, description + version match the script.


🤖 Generated by an AI review agent — advisory only. Feel free to close anything that isn't worth it.

Comment thread docs/fragments/skills/winapp-cli/maui.md Outdated
Comment thread docs/fragments/skills/winapp-cli/frameworks.md Outdated
Comment thread scripts/validate-llm-docs.ps1 Outdated
Comment thread docs/fragments/skills/winapp-cli/maui.md
Comment thread docs/fragments/skills/winapp-cli/maui.md Outdated
pictos and others added 2 commits July 9, 2026 23:48
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@nmetulev nmetulev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI-generated review — GitHub Copilot CLI (Claude Opus 4.8), requested by @nmetulev. Everything here is a suggestion for the author to accept or dismiss — nothing is blocking.

Unlike a static skim, I validated by actually running the workflow: built the winapp CLI from this branch and ran the full publish → cert generate → package → sign flow end-to-end, on both a fresh dotnet new maui project and this PR's checked-in sample.

The approach is sound and works. A fresh dotnet new mauidotnet publish -p:WindowsPackageType=None -p:SelfContained=truewinapp package --manifest obj\...\resizetizer\m\Package.appxmanifest --executable <app>.exe produced a correctly signed MSIX. The resizetizer resolved every $placeholder$ including <Identity>. So the guide/skill guidance is correct. 👍

⚠️ The problems are in the shipped sample artifact, not the documented flow (details inline):

  • H1 — the checked-in sample is missing the Windows head, so it won't compile (CS5001).
  • H2 — the sample's committed Package.appxmanifest is a hand-authored / older-style manifest whose <Identity> and logo $placeholder$ tokens the resizetizer does not resolve, so packaging the sample fails even after H1. A current dotnet new maui manifest doesn't have this problem.
  • CI reproducibility — Phase 1 scaffolds a multi-TFM project but the maui-app CI job installs only maui-windows; restore may fail.
  • Doc accuracy — the skill's description of what resolves the Identity tokens is slightly off (the conclusion is fine).

Simplest fix for H1 + H2: regenerate samples/maui-app with dotnet new maui (keep the Windows head + a current-template manifest) instead of the hand-authored files.

Non-blocking doc-sync nits (not inline — these lines are outside the PR diff):

  • llms.txt — the Skills list doesn't include maui/SKILL.md, and the Guides list doesn't include docs/guides/maui.md.
  • README.md — the samples table (~L254-263) has no maui-app row (the badge + Additional-guides link were added).

Nice work overall — the skill/guide content is genuinely useful and the core workflow checks out. The fixes above are mostly about making the shipped sample actually build and package.

Reviewed at 622c596.

Context "Phase 2: Sample Sanity Check" -Skip:$script:skip {
It "Should publish the checked-in MAUI sample project" {
Set-Location $script:sampleDir
dotnet publish ".\maui-app.csproj" `

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H1 · Sample won''t build — reproduced (CS5001). samples/maui-app/Platforms/Windows/ contains only Package.appxmanifest; the MauiWinUIApplication entry point (App.xaml, App.xaml.cs, app.manifest) is missing, so this publish fails with CSC error CS5001: Program does not contain a static 'Main' method. I verified that adding those 3 files (from dotnet new maui, namespace MauiSample.WinUI) makes the publish succeed. Simplest fix: regenerate the sample with dotnet new maui and keep the Windows head. (AI-generated; author decides.)

xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap3 rescap">

<Identity Name="$placeholder$" Publisher="$placeholder$" Version="$placeholder$" />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H2 · This manifest doesn''t resolve → winapp package fails — reproduced. These <Identity> $placeholder$ tokens are not resolved by Microsoft.Maui.Resizetizer. After a clean publish, the generated obj\...\resizetizer\m\Package.appxmanifest still contains $placeholder$ for <Identity>, <PublisherDisplayName>, <Logo>, and the tile/splash logos, and winapp package exits 1: "manifest contains unresolved placeholders: $placeholder$".

A current dotnet new maui manifest differs and does resolve fully:

  • <Identity> uses literal defaults (Name="maui-package-name-placeholder", Publisher="CN=User Name", Version="0.0.0.0") which MAUI's single-project step overwrites from ApplicationId / ApplicationPublisher / ApplicationDisplayVersion.
  • logo attributes end in .png ($placeholder$.png), which the resizetizer matches and rewrites.

This sample's manifest is hand-authored / older-style, so nothing fills those tokens. I confirmed a fresh template packages to a signed MSIX, while this sample fails even after H1 is fixed. Fix: regenerate the manifest from a current dotnet new maui. (AI-generated; author decides.)

Context "Phase 1: MAUI Guide Workflow (from scratch)" -Skip:$script:skip {
It "Should create a new MAUI project" {
Set-Location $script:tempDir
dotnet new maui -n $script:projectName

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI reproducibility (medium confidence). dotnet new maui scaffolds a multi-TFM project (net10.0-android;net10.0-ios;net10.0-maccatalyst;net10.0-windows...), but the maui-app job in test-samples.yml installs only maui-windows. Locally, publishing a multi-TFM project with just that workload failed to restore mobile runtime packs (NU1102 ... Microsoft.NETCore.App.Runtime.Mono.win-x64). Phase 1 may hit the same restore failure in CI. Worth verifying — either install the full maui workload, or strip the scaffolded project to the Windows TFM before publishing (as the checked-in maui-app.csproj already does). (AI-generated; author decides.)

<uap:VisualElements DisplayName="$placeholder$" ... Square150x150Logo="$placeholder$" Square44x44Logo="$placeholder$">
```

These are resolved at **build/publish time** by **`Microsoft.Maui.Resizetizer`** (bundled with the MAUI workload), which reads MSBuild properties (`ApplicationTitle`, `ApplicationId`, `ApplicationDisplayVersion`, `ApplicationPublisher`, the `MauiIcon`/`MauiSplashScreen` items, etc.), generates the app icon/tile/splash assets, and writes a **resolved** manifest into the intermediate output.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root-cause description is slightly off (optional). This says the source <Identity Name="$placeholder$" ...> tokens are "resolved at build/publish time by Microsoft.Maui.Resizetizer." Empirically the resizetizer does not resolve <Identity> $placeholder$. Real MAUI projects work because their source <Identity> uses literal defaults (maui-package-name-placeholder, CN=User Name, 0.0.0.0) that MAUI's single-project step overwrites from MSBuild props — the resizetizer handles the DisplayName / logo / splash-image placeholders. The practical guidance (point winapp at the generated manifest) is correct; only the mechanism description could be tightened. (AI-generated; author decides.)

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.

4 participants