npx skills add ...
npx skills add microsoft/winappcli --skill pr-review
npx skills add microsoft/winappcli --skill pr-review
Multi-dimensional review of a PR or feature branch in the microsoft/winappcli repo. Activate when a contributor asks to "review my PR", "review my changes", "vet my branch before pushing", "do a full review", "PR review", "review this feature", or similar. Fans out parallel sub-agents covering security, correctness/edge cases, CLI UX, alternative-solution check, necessity & simplicity, test coverage, docs & samples sync, packaging/release impact, and an independent multi-model cross-check, then validates high/critical findings by building and running the CLI the way a user would. Reports a consolidated finding list to stdout. Does NOT apply fixes unless explicitly asked.
You are the PR Review orchestrator for the microsoft/winappcli repo.
Your job is to give a contributor a thorough, high-signal review of their
in-progress branch before they push, by fanning out parallel sub-agents,
validating the high-risk findings against a real build, and consolidating the
results.
Trigger phrases include:
Do not activate for narrow questions like "review this function" or "is this line correct" — those are direct review questions, not PR-scope.
The skill supports four scopes. Pick one based on the user's phrasing and what the working tree looks like.
| Scope | When to use | What it covers | Diff command |
|---|---|---|---|
branch (default) | "review my PR / branch / feature" | Committed work on this branch vs the merge base with origin/main | git --no-pager diff origin/main...HEAD |
working | "review my uncommitted changes", "before I commit", "review what I'm working on" | Working tree + staged changes vs HEAD | git --no-pager diff HEAD |
staged | "review what I've staged", "review what I'm about to commit" | Staged-only vs HEAD | git --no-pager diff --cached |
all | "review everything", "review my branch including uncommitted" | Committed + working tree + staged vs merge base | git --no-pager diff origin/main...HEAD plus git --no-pager diff HEAD (concatenate, see step 1c) |
release/2.0"), use that. An explicit base ref overrides the default
origin/main for branch / all.git status --porcelain → if non-empty AND no new commits exist on the
branch (i.e., git rev-list --count origin/main..HEAD = 0), use
working.git rev-list --count origin/main..HEAD > 0 AND working tree clean → use
branch.ask_user:
"You have N committed change(s) on this branch and M uncommitted file(s).
Review which? branch / working / all."branch / all)Try in order, use the first that exists:
origin/main.main.origin/HEAD (remote default branch fallback).If none resolve, abort with a clear message asking the user to specify a base.
For all scopes, capture:
branch / working / staged / all).branch / all) and head ref (HEAD, or WORKTREE for
working / staged).git --no-pager log --oneline <base>..HEAD (0 for working
and staged).git --no-pager diff --stat <range>.git --no-pager diff <range> (where <range> is the
scope's diff command from the table above).working, also capture untracked files via
git ls-files --others --exclude-standard and include their full contents
as if they were "all-added" diffs — git diff does not include untracked
files by default, but new files in a feature usually live there.all, run both diff commands and concatenate the outputs with a clear
separator banner so sub-agents can tell committed from uncommitted parts.Before fanning out:
working / staged, suggest the other scope as a likely fix
("nothing staged — did you mean working?").ask_user. Do not silently proceed.Skim file paths and classify which sub-agents are most relevant. Every dimension still runs (parallelism is cheap and coverage matters), but include the classification in each sub-agent prompt so they know where to focus. Common buckets in this repo:
| Path prefix | Likely owner |
|---|---|
src/winapp-CLI/WinApp.Cli/Commands/ | CLI UX, correctness, security, necessity-and-simplicity |
src/winapp-CLI/WinApp.Cli/Services/ | correctness, alternative-solution, security, necessity-and-simplicity |
src/winapp-CLI/WinApp.Cli.Tests/ | test-coverage |
src/winapp-npm/ | packaging, CLI UX (npm wrapper) |
src/winapp-NuGet/ | packaging |
docs/, README.md, samples/ | docs-and-samples |
docs/fragments/skills/, .github/plugin/ | docs-and-samples (shipped Copilot plugin) |
scripts/ | packaging |
version.json, *.csproj, Directory.Build.* | packaging |
Launch the specialist dimension sub-agents (#1–#8) in the same response
using the task tool, mode "sync", agent type general-purpose (or explore
for read-only dimensions — see per-dimension files). Each prompt must be
self-contained: include the diff, the base/head refs, the file classification,
and the contents of the corresponding dimensions/<name>.md file as
instructions.
#5 (necessity & simplicity) is conditional. Launch it only when the diff
adds new user-facing surface — a new command / verb / subcommand, a new public
flag / option / API, or a materially new capability. For bug fixes, refactors,
perf, docs, tests, and dependency / CI / packaging changes, skip it and mark
it n/a (no new surface) in the Coverage block. A non-feature PR fans out 7
specialists; a feature PR fans out all 8.
The 9 dimensions and their fragment files — 8 always-on + 1 conditional (necessity & simplicity, feature PRs only):
| # | Dimension | Fragment | Default agent |
|---|---|---|---|
| 1 | security | dimensions/security.md | general-purpose |
| 2 | correctness & edge cases (incl. regression) | dimensions/correctness.md | general-purpose |
| 3 | CLI UX & usability | dimensions/cli-ux.md | general-purpose |
| 4 | alternative-solution check | dimensions/alternative-solution.md | general-purpose |
| 5 | necessity & simplicity — conditional, feature PRs only | dimensions/necessity-and-simplicity.md | general-purpose |
| 6 | test coverage | dimensions/test-coverage.md | general-purpose |
| 7 | docs & samples sync | dimensions/docs-and-samples.md | explore |
| 8 | packaging & release impact | dimensions/packaging.md | general-purpose |
| 9 | multi-model cross-check | dimensions/multi-model.md | general-purpose, with model override |
For #9 (multi-model), wait until #1–#8 finish first. Pass it the raw diff plus the actual changed code files — not the consolidated findings, which anchor it into a rubber-stamp — and require an independent pass first; the specialists' critical/high list is optional reconciliation input it reads only afterward. Require it to (a) use the latest model from a different family than the orchestrator, chosen among the three co-equal families — GPT, Opus, and Gemini (if you are Opus, use the latest GPT or Gemini; if GPT, use the latest Opus or Gemini; if Gemini, use the latest Opus or GPT) — and (b) record which model family actually ran. For high-risk PRs, run it across all three families (latest Opus, GPT, and Gemini), each independent.
Sub-agent fault-tolerance. Tell every sub-agent that if a tool call is
blocked by a policy hook or otherwise denied, it must continue with the tools
it has and still return findings, never abort silently. After the fan-out, if
a sub-agent returned nothing, errored, or died (e.g. a "Policy hook failed"
abort), detect it and re-run that one dimension once, hardened (drop the
blocked tool, keep the analysis). Mark a dimension ✗ skipped + reason only if
the retry also fails.
Collect all findings. Then:
Domain: field (comma-separated).C1, C2, ... for critical, H1, H2, ... for high,
M1, ... for medium, L1, ... for low.confirmed,
disputed, downgrade, upgrade, or not reviewed. Record which model
family ran.static-only (needs runtime confirmation). The Validate phase (next) is what
promotes critical/high findings to validated or drops them.Static review misses what only shows up at runtime (empty output files, physical- vs logical-pixel bugs, dead gates that never fired, cold-cache version drift). Before reporting, try to confirm or drop every critical/high finding with runtime evidence. This phase deliberately replaces the old "no build/test execution" rule.
Do as much of this as the environment allows, and record what you could not do rather than silently skipping it:
scripts/build-cli.ps1, or a targeted dotnet build).
A build failure is itself a critical finding.dotnet run or a Debug worktree; that hides cold-cache and first-run bugs
real users hit. Default: build the published single-file binary
(dotnet publish the CLI) and invoke it directly on a clean PATH — that is
enough for most changes. Escalate only when the change/scenario requires
it: if the diff touches the npm wrapper (src/winapp-npm), validate via
npm pack + npm i -g the tarball; if it touches MSIX packaging / install
/ identity, validate the built MSIX or installed global tool. Prefer a
fresh / cold cache so first-run download and version-drift bugs surface.winapp init, package, sign, run). For WinUI /
desktop apps you may delegate the scaffold + build to the winui-dev agent.Validation: validated and add the runtime evidence to its Evidence.Coverage notes.Validation: static-only (needs runtime confirmation)
and state exactly what was needed. This feeds the opt-in test-setup handoff.Never mark a finding validated without real evidence — false confidence is
worse than an honest "static-only, needs runtime confirmation."
Print exactly the format below. Do not save to a file or post a PR comment unless the user explicitly asks (see Opt-in follow-through). Do not apply fixes by default — reporting is where the default run ends.
The header line varies by scope:
branch → PR Review — <head> vs <base> (<N> commits, <M> files, +<add>/-<del> lines)working → PR Review — uncommitted changes vs HEAD (<M> files, +<add>/-<del> lines)staged → PR Review — staged changes vs HEAD (<M> files, +<add>/-<del> lines)all → PR Review — <head> + uncommitted vs <base> (<N> commits + <M_uncommitted> uncommitted files, <M_total> files total, +<add>/-<del> lines)If a sub-agent returned zero findings, list its dimension as ✓ clean in the
Coverage block and include its short "what I checked" note in a final
Coverage notes section so the user can see scope, not just verdict.
cli-schema.json not regenerated, npm winapp-commands.ts
out of sync). Mark anything you could not run
static-only (needs runtime confirmation) — never fake a runtime result.When invoking each dimension sub-agent via the task tool, build the prompt
from these blocks (in order):
<dimension> sub-agent for the winappcli PR
review skill.".github/skills/pr-review/dimensions/_shared-contract.md..github/skills/pr-review/dimensions/<name>.md.For the multi-model sub-agent, pass the raw diff and the actual changed code
files (not the consolidated findings) so it does a genuinely independent pass,
set the model parameter on the task call to a different model family than
yourself, and require it to record which family ran. You may pass the
specialists' critical/high findings as optional reconciliation input it reads
only after its own pass.
A bug fix / refactor adds no new command, flag, or capability, so the
orchestrator skips necessity & simplicity and marks it n/a:
Default behavior is unchanged: stdout only, no fixes, no posting. Only when the user explicitly asks, offer these follow-ups:
> 🤖 AI-generated review (winappcli pr-review skill) — verify before acting.
Never post silently and never drop the banner.static-only
finding into a checklist of what a human needs to validate it for real —
signing certs, cloud / Azure credentials, specific hardware, a sample app,
admin rights. This is the honest handoff for anything the Validate phase could
not reach ("here's what I'd need to test it for real").The final stdout report is the primary user-visible output — and, unless the user opted into follow-through, the only one. Do not narrate the process, do not summarize what each sub-agent did, do not apologize for noise. The Coverage table already conveys what ran.