Add winapp-maui skill for the MAUI resizetizer manifest dependency#610
Add winapp-maui skill for the MAUI resizetizer manifest dependency#610pictos wants to merge 3 commits into
Conversation
.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>
There was a problem hiding this comment.
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.mdskill fragment plus its generatedSKILL.mdin.github/plugin/skills/winapp-cli/maui/and.claude/skills/winapp-maui/. - Registers
mauiin the doc-generation and validation scripts (generate-llm-docs.ps1,validate-llm-docs.ps1). - Adds cross-links (frameworks table row +
.NET MAUIsection, 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
left a comment
There was a problem hiding this comment.
🤖 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.ps1 → exit 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---manifestshortcut don't hold for theWindowsPackageType=Noneflow the skill documents (medium; originally high, downgraded on cross-check). - M3
frameworks.md— standalonewinapp-mauiskill vs the frameworks+guide convention (medium, design call). - M4
validate-llm-docs.ps1— pre-existing: validate list omitsui-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.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
nmetulev
left a comment
There was a problem hiding this comment.
🤖 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 maui → dotnet publish -p:WindowsPackageType=None -p:SelfContained=true → winapp 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. 👍
- H1 — the checked-in sample is missing the Windows head, so it won't compile (
CS5001). - H2 — the sample's committed
Package.appxmanifestis 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 currentdotnet new mauimanifest doesn't have this problem. - CI reproducibility — Phase 1 scaffolds a multi-TFM project but the
maui-appCI job installs onlymaui-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 includemaui/SKILL.md, and the Guides list doesn't includedocs/guides/maui.md.README.md— the samples table (~L254-263) has nomaui-approw (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" ` |
There was a problem hiding this comment.
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$" /> |
There was a problem hiding this comment.
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 fromApplicationId/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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.)
Summary
Adds a dedicated
winapp-mauiskill 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.appxmanifestfull of MAUI-specific$placeholder$tokens (DisplayName, Logo, Identity Name/Publisher/Version, tile/splash logos).winapp packageonly auto-resolves its own$targetnametoken$/$targetentrypoint$tokens — it does not understand MAUI's$placeholder$tokens, so pointing it at the source manifest fails with: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 --manifestat 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
docs/fragments/skills/winapp-cli/maui.mdand generatedSKILL.mdin.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.mauiinscripts/generate-llm-docs.ps1($SkillNames,$SkillDescriptions,$SkillCommandMap= empty — links to guidance, likeframeworks) and inscripts/validate-llm-docs.ps1.winapp-frameworks(guides table row +### .NET MAUInote + related-skills bullet) andwinapp-troubleshoot(error-table row + related-skills bullet).Validation
SKILL.mdfiles verified byte-identical togenerate-llm-docs.ps1output (ignoring the version line, which the release build stamps)..claude/skills/winapp-maui/SKILL.mdverified byte-identical to the plugin source (whatsync-claude-plugin.ps1produces).--manifestat the resizetizer manifest.