Skip to content

Commit 694301f

Browse files
authored
Merge pull request #200 from microsoft/nmetulev-winapp-0-7-migration
Keep skill links inside each skill directory (marketplace link validation)
2 parents c1b6053 + 55c8662 commit 694301f

10 files changed

Lines changed: 46 additions & 23 deletions

File tree

‎.github/workflows/pr-validation.yml‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,27 @@ jobs:
137137
if not skill_dirs:
138138
errors.append(f"No immediate skill directories found under {skills_root}")
139139
for skill_dir in skill_dirs:
140-
if not (skill_dir / "SKILL.md").is_file():
140+
skill_md = skill_dir / "SKILL.md"
141+
if not skill_md.is_file():
141142
errors.append(f"Immediate skill directory lacks SKILL.md: {skill_dir}")
143+
continue
144+
# Mirrors vally's valid-refs lint used by marketplaces such as
145+
# awesome-copilot: markdown links must resolve inside the skill
146+
# directory. Name sibling skills in plain text instead.
147+
body = re.sub(r"(?ms)^(```|~~~).*?^\1", "", skill_md.read_text(encoding="utf-8"))
148+
body = re.sub(r"`[^`\n]*`", "", body)
149+
targets = re.findall(r"\]\(([^)\s]+)", body) + re.findall(r"(?m)^\s*\[[^\]]+\]:\s*(\S+)", body)
150+
for target in targets:
151+
if re.match(r"^[A-Za-z][A-Za-z0-9+.-]*:", target) or target.startswith("#"):
152+
continue
153+
relative = target.split("#", 1)[0]
154+
if not relative:
155+
continue
156+
resolved = (skill_dir / relative).resolve()
157+
if not resolved.is_relative_to(skill_dir.resolve()):
158+
errors.append(f"{skill_md}: link '{target}' points outside the skill directory; name the other skill in plain text")
159+
elif not resolved.exists():
160+
errors.append(f"{skill_md}: link '{target}' does not exist")
142161
143162
forbidden_portable_paths = (
144163
".claude-plugin",

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ The `version-bump` and `changelog-entry` CI jobs enforce this.
2929

3030
### Fixed
3131

32+
- Replace cross-skill markdown links with plain-text skill names so each skill
33+
is self-contained and passes marketplace link validation (vally `valid-refs`),
34+
which blocked the awesome-copilot listing update. CI now enforces this.
35+
3236
### Removed
3337

3438
### Deprecated

‎plugins/winui/agent-plugin/skills/winui-code-review/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ Run a code review **after the app builds and before committing**. This catches q
99

1010
### How to Review
1111

12-
Read through the project's XAML and C# files and check each section below. For analyzer setup, see [winui-dev-workflow](../winui-dev-workflow/SKILL.md); if it isn't installed, tell the user its checks didn't run.
12+
Read through the project's XAML and C# files and check each section below. For analyzer setup, see `winui-dev-workflow`; if it isn't installed, tell the user its checks didn't run.
1313

14-
Before reporting an API mismatch or recommending a replacement, verify it against the **restored app project's** references with CLI 0.7+ `winapp find-api`, for example `winapp find-api members NavigationView --filter selected --json --project-dir <app-project-dir>`. See [winui-design](../winui-design/SKILL.md) for batch property checks and project selection; machine-SDK results are not proof of app-package availability.
14+
Before reporting an API mismatch or recommending a replacement, verify it against the **restored app project's** references with CLI 0.7+ `winapp find-api`, for example `winapp find-api members NavigationView --filter selected --json --project-dir <app-project-dir>`. See `winui-design` for batch property checks and project selection; machine-SDK results are not proof of app-package availability.
1515

1616
The analyzer catches a curated set of WinUI 3 / Windows App SDK issues with categorized 4-digit IDs:
1717

@@ -42,7 +42,7 @@ Use the installed package's diagnostic help links for rule details. Check inheri
4242
### Native AOT / Trimming (When Intended)
4343

4444
- [ ] The published artifact was tested (a Release JIT run is not AOT validation), with IL/CsWinRT warnings fixed rather than suppressed
45-
- [ ] ABI-crossing types are partial; JSON and runtime bindings use source generation — see [source-generator patterns](../winui-packaging/references/sourcegen-patterns.md)
45+
- [ ] ABI-crossing types are partial; JSON and runtime bindings use source generation — see `winui-packaging`'s `references/sourcegen-patterns.md`
4646

4747
### Accessibility
4848

‎plugins/winui/agent-plugin/skills/winui-design/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Don't size the window by setting `Width`/`Height` on the root `Grid` — that cl
103103
<TextBlock Text="{x:Bind Vm.Status, Mode=OneWay}" />
104104
```
105105

106-
In a page/window, `x:Bind` resolves against code-behind (e.g., its `Vm` property), not `DataContext`. Use `x:DataType` on typed **DataTemplates**, not on `Page` to set a VM. Runtime `{Binding}`/`DisplayMemberPath` can be appropriate; for AOT, their source classes may need `partial` plus `[WinRT.GeneratedBindableCustomProperty]`. See [source-generator patterns](../winui-packaging/references/sourcegen-patterns.md) instead of treating all runtime binding as unsupported.
106+
In a page/window, `x:Bind` resolves against code-behind (e.g., its `Vm` property), not `DataContext`. Use `x:DataType` on typed **DataTemplates**, not on `Page` to set a VM. Runtime `{Binding}`/`DisplayMemberPath` can be appropriate; for AOT, their source classes may need `partial` plus `[WinRT.GeneratedBindableCustomProperty]`. See `winui-packaging`'s `references/sourcegen-patterns.md` instead of treating all runtime binding as unsupported.
107107

108108
### `TextBox` two-way needs `UpdateSourceTrigger=PropertyChanged`
109109

‎plugins/winui/agent-plugin/skills/winui-dev-workflow/SKILL.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ dotnet add .\MyApp.csproj package Microsoft.Windows.SDK.BuildTools.WinUIAnalyzer
2828

2929
Keep `PrivateAssets="all"` on the reference. It loads in normal CLI, IDE, and CI builds; WinApp CLI does not inject it. If the package is unavailable, continue and tell the user its checks for potential runtime issues did not run. Undo only an incomplete reference added by this attempt; do not remove existing references or hide other restore failures.
3030

31-
For other packages, prefer the latest stable unless the project has a version policy or the user requests a specific version. Before coding API assumptions, use `winapp find-api` scoped to the restored app with `--project-dir <app-project-dir>` (or `--project <name>` in a solution); see [winui-design](../winui-design/SKILL.md).
31+
For other packages, prefer the latest stable unless the project has a version policy or the user requests a specific version. Before coding API assumptions, use `winapp find-api` scoped to the restored app with `--project-dir <app-project-dir>` (or `--project <name>` in a solution); see `winui-design`.
3232

3333
### Build & Run (JIT Development)
3434

3535
```powershell
3636
winapp run . --detach --json
3737
```
38-
For UI testing, see [winui-ui-testing](../winui-ui-testing/SKILL.md), which chooses the execution target itself.
38+
For UI testing, see `winui-ui-testing`, which chooses the execution target itself.
3939

4040
Ordinary `winapp run` uses the build/JIT path, **even with `-c Release`**; it does not validate Native AOT. Use an explicit `.csproj` when project selection is ambiguous; see `winapp run --help` for options.
4141

@@ -48,7 +48,7 @@ For intended AOT deployment, set `<PublishAot>true</PublishAot>` in the app proj
4848
winapp run . --aot -c Release --arch <x64|arm64> --detach --json
4949
winapp run . --aot -c Release --arch <x64|arm64> -p PublishAot=true --detach --json
5050
```
51-
Fix IL/CsWinRT warnings rather than suppressing them. See [AOT/source-generator patterns](../winui-packaging/references/sourcegen-patterns.md).
51+
Fix IL/CsWinRT warnings rather than suppressing them. See `winui-packaging`'s `references/sourcegen-patterns.md`.
5252

5353
### Diagnosing Crashes
5454

@@ -82,7 +82,7 @@ Run attached with `--debug-output` and **invoke it with `mode: "async"`**, then
8282
| WinApp CLI | 0.7+ |
8383
| Native AOT only | MSVC C++ build tools (Visual Studio or Build Tools, **Desktop development with C++** workload, target-architecture tools); not needed for normal builds |
8484

85-
If WinApp CLI is missing or older than 0.7, install or upgrade it using [winui-setup](../winui-setup/SKILL.md) without asking (it needs no admin rights) and tell the user. Ask before installing anything that needs admin rights — the .NET SDK, Developer Mode, or the [Native AOT toolchain](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/); do not work around them.
85+
If WinApp CLI is missing or older than 0.7, install or upgrade it using `winui-setup` without asking (it needs no admin rights) and tell the user. Ask before installing anything that needs admin rights — the .NET SDK, Developer Mode, or the [Native AOT toolchain](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/); do not work around them.
8686

8787
### Critical Rules
8888

@@ -93,4 +93,4 @@ If WinApp CLI is missing or older than 0.7, install or upgrade it using [winui-s
9393

9494
### References
9595

96-
- [winui-packaging](../winui-packaging/SKILL.md) — release packaging directly from the project; no development registration required.
96+
- `winui-packaging` — release packaging directly from the project; no development registration required.

‎plugins/winui/agent-plugin/skills/winui-packaging/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: winui-packaging
33
description: "MSIX packaging, code signing, and distribution for WinUI 3 apps with WinApp CLI 0.7+ — SDK-native project packaging, Native AOT, certificates, self-contained deployment, CI/CD, and Microsoft Store handoff. Use when preparing for release, creating MSIX installers, managing certificates, setting up CI/CD packaging, or publishing to the Microsoft Store."
44
---
55

6-
Requires **WinApp CLI 0.7+**. For analyzer setup, see [winui-dev-workflow](../winui-dev-workflow/SKILL.md).
6+
Requires **WinApp CLI 0.7+**. For analyzer setup, see `winui-dev-workflow`.
77

88
### Quick Reference
99

@@ -23,7 +23,7 @@ Requires **WinApp CLI 0.7+**. For analyzer setup, see [winui-dev-workflow](../wi
2323
- Pass the **explicit project file**, not `.` or a guessed `bin` folder. WinUI project packaging uses SDK-native `dotnet publish` packaging, defaults to **Release**, and preserves project AOT settings.
2424
- Check manifest identity, target architectures, the SDK for the app's TFM, and release warnings.
2525
- For Native AOT, set `<PublishAot>true</PublishAot>` in the project and fix IL/CsWinRT warnings; there is **no `winapp package --aot`**. AOT also needs the MSVC C++ build tools. See [source-generator patterns](references/sourcegen-patterns.md).
26-
- Project packaging rejects `WindowsPackageType=None`; restore the packaged setting first (see [winui-dev-workflow](../winui-dev-workflow/SKILL.md) Critical Rules).
26+
- Project packaging rejects `WindowsPackageType=None`; restore the packaged setting first (see `winui-dev-workflow` Critical Rules).
2727

2828
Do **not** run/register/unregister a development package just to produce release artifacts. Project packaging builds without a development `winapp run --no-launch` step. For WinUI SDK-native packaging, do not pass layout overrides `--manifest`, `--executable`, or `--skip-pri`; fix the project/manifest instead.
2929

@@ -55,7 +55,7 @@ winapp sign .\MyApp.msix .\prod.pfx --timestamp http://timestamp.digicert.com
5555
`--timestamp` belongs to **`winapp sign`**, not `winapp package`. Use an approved timestamp service and protect the PFX/password.
5656

5757
#### Step 5: Install or Distribute
58-
When installation/testing is part of the task, choose the target per [winui-ui-testing](../winui-ui-testing/SKILL.md) Step 1, and get consent for certificate trust and dependency provisioning on that machine. Packaging alone is not permission to install an app.
58+
When installation/testing is part of the task, choose the target per `winui-ui-testing` Step 1, and get consent for certificate trust and dependency provisioning on that machine. Packaging alone is not permission to install an app.
5959

6060
### Self-Contained Does Not Mean Single-File
6161

‎plugins/winui/agent-plugin/skills/winui-packaging/references/sourcegen-patterns.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Source Generator Patterns — Detailed Reference
22

3-
Patterns for Native AOT and trimming in WinUI 3. See [SKILL.md](../SKILL.md) for project packaging and [winui-dev-workflow](../../winui-dev-workflow/SKILL.md) for analyzer setup and publish runs.
3+
Patterns for Native AOT and trimming in WinUI 3. See [SKILL.md](../SKILL.md) for project packaging and `winui-dev-workflow` for analyzer setup and publish runs.
44

55
---
66

‎plugins/winui/agent-plugin/skills/winui-setup/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ If the user declines or dismisses UAC, continue to the summary and print the com
132132

133133
Report these separately from the base toolchain. `winapp target snapshot sandbox --json` inspects an existing
134134
guest without starting or repairing it; "no target running" alone does not
135-
mean the Windows feature is unavailable. [winui-ui-testing](../winui-ui-testing/SKILL.md)
135+
mean the Windows feature is unavailable. `winui-ui-testing`
136136
Step 1 defines what to do when Windows Sandbox is unavailable.
137137

138138
Enabling Windows Sandbox is a **user action** (admin plus a reboot): ask the user

‎plugins/winui/agent-plugin/skills/winui-ui-testing/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description: "Automated UI testing for Windows desktop apps — generate a batch
99

1010
Windows Sandbox keeps synthetic input off the user's desktop; target selection is in Step 1. Discover the installed contract with `winapp run --help`, `winapp target --help`, and `winapp ui <verb> --help`. Use `--on sandbox`, not `--sandbox` or a top-level `sandbox` command. Do not enable Windows features or launch an app without the task's permission.
1111

12-
- Prerequisites and enablement: see [winui-setup](../winui-setup/SKILL.md).
12+
- Prerequisites and enablement: see `winui-setup`.
1313
- Project builds/publishes execute on the **host**; deployment, app launch, and `ui --on sandbox` execute in the **guest**. Run the batch script below on the host, not inside `target exec` (which would double-route).
1414
- Real input and capture require an unlocked host and a connected, nonminimized Sandbox client. Tree inspection may work while input cannot; a readable tree is not an input-readiness check.
1515
- `winapp target snapshot sandbox --json` is a read-only readiness query: it neither starts nor reconnects a guest. Use it to diagnose readiness rather than probing the user's desktop.
@@ -24,7 +24,7 @@ Core verbs: `list-windows`, `inspect`, `search`, `get-property`, `get-value`, `w
2424

2525
### Step 1: Select a target, then keep the PID and target together
2626

27-
Prefer `sandbox` when Windows Sandbox is available; otherwise tell the user and choose `local`. **If the user explicitly requested Windows Sandbox and it is unavailable, stop** and point them to the enablement steps in [winui-setup](../winui-setup/SKILL.md). A stopped guest does not prove unavailability: `target snapshot` can report no running target while the feature is enabled. App build/test failures are not Sandbox unavailability. The same policy applies to diagnostics: unpackaged apps can't use guest `--debug-output`, so diagnose them locally unless Sandbox was explicitly requested.
27+
Prefer `sandbox` when Windows Sandbox is available; otherwise tell the user and choose `local`. **If the user explicitly requested Windows Sandbox and it is unavailable, stop** and point them to the enablement steps in `winui-setup`. A stopped guest does not prove unavailability: `target snapshot` can report no running target while the feature is enabled. App build/test failures are not Sandbox unavailability. The same policy applies to diagnostics: unpackaged apps can't use guest `--debug-output`, so diagnose them locally unless Sandbox was explicitly requested.
2828

2929
Pass the selected target to the template: it launches with `winapp run . --on sandbox --detach --json` for a guest, or omits `--on sandbox` for local execution. Reuse an already-running app only when its captured target matches the selected target and the guest has not been recreated. Never pass a guest PID to default-host `winapp ui`. If a target becomes unavailable after selection, report it and select again under the same policy; the script itself never retries in another target.
3030

‎plugins/winui/agent-plugin/skills/winui-wpf-migration/SKILL.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: "Migrate WPF applications to WinUI 3 — namespace replacement (Sys
55

66
### Migration Process
77

8-
Use the **WinApp CLI 0.7+** prerequisites and per-app analyzer setup in [winui-dev-workflow](../winui-dev-workflow/SKILL.md). The normal SDK path needs .NET 8.0.100 or later **and** the SDK required by the target TFM; Native AOT additionally needs MSVC/Desktop C++ tools. Handle missing prerequisites as described there.
8+
Use the **WinApp CLI 0.7+** prerequisites and per-app analyzer setup in `winui-dev-workflow`. The normal SDK path needs .NET 8.0.100 or later **and** the SDK required by the target TFM; Native AOT additionally needs MSVC/Desktop C++ tools. Handle missing prerequisites as described there.
99

1010
#### Step 1: Audit the WPF Source
1111
Before writing code, inventory WPF-specific APIs:
@@ -19,15 +19,15 @@ List: WPF controls used, custom MVVM framework, imaging APIs, threading patterns
1919
```powershell
2020
winapp new --name <AppName> --template winui-mvvm --template-version latest --use-defaults
2121
```
22-
Immediately set `<RootNamespace>` in `.csproj` to match the WPF namespace. Update `x:Class` in `App.xaml`, `MainWindow.xaml` and their code-behind files. Add the analyzer per [winui-dev-workflow](../winui-dev-workflow/SKILL.md). Build to verify before porting any code.
22+
Immediately set `<RootNamespace>` in `.csproj` to match the WPF namespace. Update `x:Class` in `App.xaml`, `MainWindow.xaml` and their code-behind files. Add the analyzer per `winui-dev-workflow`. Build to verify before porting any code.
2323

2424
Before implementing API replacements, restore the app project and check its exact references from the WinUI project directory, not the old WPF project or machine SDK:
2525
```powershell
2626
winapp find-api DispatcherQueue --json --project-dir .
2727
winapp find-api members DispatcherQueue --filter TryEnqueue --json --project-dir .
2828
winapp find-api check-property ListView ItemsSource SelectionMode --json --project-dir .
2929
```
30-
Use `winapp find-ui "<intent>"` for usage samples; see [winui-design](../winui-design/SKILL.md) for project selection and batch API checks.
30+
Use `winapp find-ui "<intent>"` for usage samples; see `winui-design` for project selection and batch API checks.
3131

3232
#### Step 3: Replace Namespaces
3333

@@ -74,7 +74,7 @@ Get via `DispatcherQueue.GetForCurrentThread()`. No `Application.Current.Dispatc
7474
Delete custom `ObservableObject`/`RelayCommand`/`DelegateCommand`. Use CommunityToolkit.Mvvm:
7575
- `INotifyPropertyChanged` base → `ObservableObject` with `[ObservableProperty]` partial properties (fix MVVMTK0045; don't keep fields)
7676
- Custom `RelayCommand` → `[RelayCommand]` attribute
77-
- Prefer `{x:Bind}` for known types; keep runtime `{Binding}`/`DisplayMemberPath` where needed. See [source-generator patterns](../winui-packaging/references/sourcegen-patterns.md) for binding modes, `x:DataType`, and AOT-safe runtime binding.
77+
- Prefer `{x:Bind}` for known types; keep runtime `{Binding}`/`DisplayMemberPath` where needed. See `winui-packaging`'s `references/sourcegen-patterns.md` for binding modes, `x:DataType`, and AOT-safe runtime binding.
7878
- `DynamicResource` → `{ThemeResource}`
7979

8080
#### Step 8: Replace Resources
@@ -86,7 +86,7 @@ Delete custom `ObservableObject`/`RelayCommand`/`DelegateCommand`. Use Community
8686

8787
- ❌ NEVER reference `PresentationCore`, `PresentationFramework`, or `System.Windows.Controls` assemblies
8888
- ❌ NEVER add `<UseWPF>true</UseWPF>`
89-
- Keep packaged as the default; see [winui-dev-workflow](../winui-dev-workflow/SKILL.md) Critical Rules for unpackaged experiments.
89+
- Keep packaged as the default; see `winui-dev-workflow` Critical Rules for unpackaged experiments.
9090
- ❌ NEVER delete `Package.appxmanifest`
9191
- ❌ NEVER overwrite `App.xaml` / `App.xaml.cs` — merge WPF code into the WinUI 3 boilerplate
9292
- ✅ Launch with project-mode `winapp run`, not the .exe directly.
@@ -108,4 +108,4 @@ dotnet build .\MyApp.csproj -p:Platform=x64
108108
winapp run .\MyApp.csproj --detach --json
109109
```
110110

111-
For UI validation, see [winui-ui-testing](../winui-ui-testing/SKILL.md); for crash diagnostics, see [winui-dev-workflow](../winui-dev-workflow/SKILL.md). If AOT is intended, also test the published artifact via the workflow's AOT path; the run above is JIT, even in Release.
111+
For UI validation, see `winui-ui-testing`; for crash diagnostics, see `winui-dev-workflow`. If AOT is intended, also test the published artifact via the workflow's AOT path; the run above is JIT, even in Release.

0 commit comments

Comments
 (0)