From 312617764fc3e57cc64bf1a5dbf695afcaa34788 Mon Sep 17 00:00:00 2001 From: redth Date: Thu, 12 Feb 2026 15:59:30 -0500 Subject: [PATCH 01/18] Add dotnet-maui-doctor skill and refs Add a new .agents/skills/dotnet-maui-doctor skill bundle. Includes SKILL.md describing an autonomous workflow to detect and remediate .NET MAUI environment issues and platform-specific reference docs for installation commands, platform requirements, troubleshooting, Microsoft OpenJDK guidance, and a WorkloadDependencies discovery guide that pulls authoritative versions from NuGet. Documents validation/remediation steps for .NET SDK, workloads, JDK, Android SDK, Xcode, and Windows SDK (macOS/Windows/Linux) and includes a temporary recommendation to prefer Microsoft OpenJDK (JDK 21) until manifests are updated. --- .agents/skills/dotnet-maui-doctor/SKILL.md | 160 +++++++++ .../references/installation-commands-macos.md | 60 ++++ .../installation-commands-windows.md | 17 + .../references/installation-commands.md | 175 ++++++++++ .../references/microsoft-openjdk.md | 111 ++++++ .../references/platform-requirements-linux.md | 36 ++ .../references/platform-requirements-macos.md | 36 ++ .../platform-requirements-windows.md | 35 ++ .../references/troubleshooting-macos.md | 79 +++++ .../references/troubleshooting-windows.md | 34 ++ .../references/troubleshooting.md | 316 ++++++++++++++++++ .../workload-dependencies-discovery.md | 191 +++++++++++ 12 files changed, 1250 insertions(+) create mode 100644 .agents/skills/dotnet-maui-doctor/SKILL.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/installation-commands.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/troubleshooting.md create mode 100644 .agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md diff --git a/.agents/skills/dotnet-maui-doctor/SKILL.md b/.agents/skills/dotnet-maui-doctor/SKILL.md new file mode 100644 index 0000000000..c4216f7245 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/SKILL.md @@ -0,0 +1,160 @@ +--- +name: dotnet-maui-doctor +description: Diagnoses and fixes .NET MAUI development environment issues. Validates .NET SDK, workloads, Java JDK, Android SDK, Xcode, and Windows SDK. All version requirements discovered dynamically from NuGet WorkloadDependencies.json - never hardcoded. Use when: setting up MAUI development, build errors mentioning SDK/workload/JDK/Android, "Android SDK not found", "Java version" errors, "Xcode not found", environment verification after updates, or any MAUI toolchain issues. Works on macOS, Windows, and Linux. +--- + +# .NET MAUI Doctor + +Validate and fix .NET MAUI development environments. All version requirements are discovered dynamically from NuGet APIs — never hardcode versions. + +## Important: .NET Version Currency + +Your training data may be outdated regarding .NET versions. .NET ships new major releases annually (November). Always check the releases-index.json (Task 2) to discover the **latest active major release** — do not assume your training data reflects the current version. For example, if you know about .NET 9.0 but the releases index shows .NET 10.0 as active, use .NET 10.0. + +## Behavior + +- Run through ALL tasks autonomously +- Re-validate after each fix +- Iterate until complete or no further actions possible +- After detecting platform (Task 1), load only the matching platform-specific references + +## Workflow + +### Task 1: Detect Environment + +```bash +# macOS +sw_vers && uname -m + +# Windows +systeminfo | findstr /B /C:"OS Name" /C:"OS Version" + +# Linux +cat /etc/os-release && uname -m +``` + +After detection, load the matching platform references: +- **macOS**: `references/platform-requirements-macos.md`, `references/installation-commands-macos.md`, `references/troubleshooting-macos.md` +- **Windows**: `references/platform-requirements-windows.md`, `references/installation-commands-windows.md`, `references/troubleshooting-windows.md` +- **Linux**: `references/platform-requirements-linux.md` + +### Task 2: Check .NET SDK + +```bash +dotnet --info +``` + +Compare installed vs `latest-sdk` from https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json where `support-phase` is `"active"`. + +### Task 3: Check MAUI Workloads + +| Workload | macOS | Windows | Linux | +|----------|-------|---------|-------| +| `maui` | Required | Required | ❌ Use `maui-android` | +| `maui-android` | Alias | Alias | Required | +| `android` | Required | Required | Required | +| `ios` | Required | Optional | N/A | + +### Task 4: Discover Requirements from NuGet + +See `references/workload-dependencies-discovery.md` for complete process. + +Query NuGet for workload manifest → extract `WorkloadDependencies.json` → get: +- `jdk.version` range and `jdk.recommendedVersion` +- `androidsdk.packages`, `buildToolsVersion`, `apiLevel` +- `xcode.version` range + +### Task 5: Validate Java JDK + +**Only Microsoft OpenJDK supported.** Verify `java -version` output contains "Microsoft". See `references/microsoft-openjdk.md` for detection paths and JAVA_HOME guidance. + +> **⚠️ TEMPORARY WORKAROUND**: Recommend JDK 21 regardless of `jdk.recommendedVersion` until WorkloadDependencies.json is updated. Rule: If WorkloadDependencies suggests ≤21, recommend 21. If >21, use that value. + +### Task 6: Validate Android SDK + +Check packages from `androidsdk.packages`, `buildToolsVersion`, `apiLevel` (Task 4). See `references/installation-commands.md` for sdkmanager commands. + +### Task 7: Validate Xcode (macOS Only) + +```bash +xcodebuild -version +``` + +Compare against `xcode.version` range from Task 4. See `references/installation-commands-macos.md`. + +### Task 8: Validate Windows SDK (Windows Only) + +```powershell +Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" +``` + +See `references/installation-commands-windows.md`. + +### Task 9: Remediation + +See `references/installation-commands.md` for all commands. + +Key rules: +- **Workloads**: Always use `--version` flag. Never use `workload update` or `workload repair`. +- **JDK**: Only install Microsoft OpenJDK. +- **Android SDK**: Use `sdkmanager` (from Android SDK command-line tools). On Windows use `sdkmanager.bat`. + +### Task 10: Re-validate + +After each fix, re-run the relevant validation task. Iterate until all checks pass. + +## Validation + +A successful run produces: +- .NET SDK installed and matches an active release +- All required workloads installed with consistent versions +- Microsoft OpenJDK detected (`java -version` contains "Microsoft") +- All required Android SDK packages installed (per WorkloadDependencies.json) +- Xcode version in supported range (macOS only) +- Windows SDK detected (Windows only) + +### Build Verification (Recommended) + +After all checks pass, create and build a test project to confirm the environment actually works: + +```bash +TEMP_DIR=$(mktemp -d) +dotnet new maui -o "$TEMP_DIR/MauiTest" +dotnet build "$TEMP_DIR/MauiTest" +rm -rf "$TEMP_DIR" +``` + +On Windows, use `$env:TEMP` or `New-TemporaryFile` for the temp directory. + +If the build succeeds, the environment is verified. If it fails, use the error output to diagnose remaining issues. + +### Run Verification (Optional — Ask User First) + +As of the latest .NET 10 SDK (10.0.103), `dotnet run` works for MAUI projects. After a successful build, **ask the user** if they want to launch the app on a target platform to verify end-to-end: + +```bash +# Replace net10.0 with the current major .NET version +dotnet run -f net10.0-android +dotnet run -f net10.0-ios # macOS only +dotnet run -f net10.0-maccatalyst # macOS only +dotnet run -f net10.0-windows # Windows only +``` + +Only run the target frameworks relevant to the user's platform and intent. This step deploys to an emulator/simulator/device, so confirm with the user before proceeding. + +## References + +- `references/workload-dependencies-discovery.md` — NuGet API discovery process +- `references/microsoft-openjdk.md` — JDK detection paths, identification, JAVA_HOME +- `references/installation-commands.md` — .NET workloads, Android SDK (sdkmanager) +- `references/troubleshooting.md` — Common errors and solutions +- `references/platform-requirements-{platform}.md` — Platform-specific requirements +- `references/installation-commands-{platform}.md` — Platform-specific install commands +- `references/troubleshooting-{platform}.md` — Platform-specific troubleshooting + +Official docs: +- [.NET MAUI Installation](https://learn.microsoft.com/en-us/dotnet/maui/get-started/installation) +- [.NET SDK Downloads](https://dotnet.microsoft.com/download) +- [Microsoft OpenJDK](https://learn.microsoft.com/en-us/java/openjdk/install) +- [Android SDK Command-Line Tools](https://developer.android.com/studio#command-line-tools-only) +- [Xcode Downloads](https://developer.apple.com/xcode/) diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md b/.agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md new file mode 100644 index 0000000000..34131f5b5c --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md @@ -0,0 +1,60 @@ +# macOS Installation Commands + +## Xcode + +### Install Xcode + +**Do not install Xcode from the App Store** — it can auto-update to a version newer than what .NET MAUI supports. + +Download a specific version from [Apple Developer Downloads](https://developer.apple.com/download/all/), matching the `xcode.version` range from WorkloadDependencies.json. + +### Install Command Line Tools + +```bash +xcode-select --install +``` + +### List Xcode Installations + +```bash +ls -d /Applications/Xcode*.app 2>/dev/null +xcodebuild -version +xcode-select -p +``` + +### Set Active Xcode Version + +```bash +sudo xcode-select -s /Applications/Xcode.app/Contents/Developer +``` + +### Accept Xcode License + +```bash +sudo xcodebuild -license accept +``` + +### Verify Xcode Installation + +```bash +xcodebuild -version +xcrun simctl list devices available +``` + +--- + +## iOS Simulators + +Only create a simulator if none exist. Prefer a recent iPhone device type with the latest available runtime. + +```bash +# Check if any simulators already exist +xcrun simctl list devices available + +# If none exist, find the latest iPhone device type and runtime +xcrun simctl list devicetypes | grep iPhone +xcrun simctl list runtimes | grep iOS + +# Create one using the newest iPhone type and latest iOS runtime +xcrun simctl create "iPhone 16 Pro" "com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro" "com.apple.CoreSimulator.SimRuntime.iOS-18-0" +``` diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md b/.agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md new file mode 100644 index 0000000000..553adcc18f --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md @@ -0,0 +1,17 @@ +# Windows Installation Commands + +## Windows SDK + +The Windows SDK is required for WinUI 3 / Windows targets. + +### Detect Windows SDK + +```powershell +Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue +``` + +### Install Windows SDK + +The Windows SDK is typically installed as part of the .NET MAUI workload or via the Visual Studio Installer. + +For standalone installation, see: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands.md b/.agents/skills/dotnet-maui-doctor/references/installation-commands.md new file mode 100644 index 0000000000..91ec6665d5 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/installation-commands.md @@ -0,0 +1,175 @@ +# Installation Commands Reference + +Commands for installing and validating .NET MAUI development dependencies. + +**See also platform-specific references:** +- macOS: `installation-commands-macos.md` +- Windows: `installation-commands-windows.md` + +--- + +**Important**: All specific versions shown below are placeholders. Always discover the actual versions to use: +- **SDK/Workload versions**: Query releases-index.json and NuGet APIs (see `workload-dependencies-discovery.md`) +- **Android SDK packages**: From `androidsdk` in WorkloadDependencies.json +- **JDK version**: From `jdk.version` in WorkloadDependencies.json + +## .NET SDK + +For installation instructions, see the official docs: https://dotnet.microsoft.com/download + +For scripted/CI installs, use the [dotnet-install scripts](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script). + +--- + +## .NET Workloads + +**Always use explicit workload set version** to ensure consistent, reproducible installs. + +First, find the latest workload set version using the process in `workload-dependencies-discovery.md`: +```bash +# Discover NuGet search endpoint from service index +NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ + jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) + +# Query for latest workload set +# SDK band = first 2 segments of SDK version (e.g., 10.0 from 10.0.102) +curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.$SDK_BAND&prerelease=false" | \ + jq '.data[] | select(.id | test("^Microsoft.NET.Workloads.$SDK_BAND.[0-9]+$")) | {id, version}' + +# Convert NuGet version to CLI version: +# NuGet A.B.C → CLI A.0.B (e.g., NuGet 10.102.0 → CLI 10.0.102) +``` + +Then install with explicit version: +```bash +# Full MAUI installation (recommended) +dotnet workload install maui --version $WORKLOAD_VERSION + +# Individual workloads +dotnet workload install android --version $WORKLOAD_VERSION +dotnet workload install ios --version $WORKLOAD_VERSION # macOS only meaningful +dotnet workload install maccatalyst --version $WORKLOAD_VERSION # macOS only meaningful + +# Multiple at once +dotnet workload install maui android ios maccatalyst --version $WORKLOAD_VERSION +``` + +### List Installed Workloads + +```bash +dotnet workload list +``` + +### ⚠️ Commands to Avoid + +**Never use these commands** - they can cause version inconsistencies: +- ❌ `dotnet workload update` - Can introduce mixed versions +- ❌ `dotnet workload repair` - May not fix version issues +- ❌ `dotnet workload install` without `--version` - Gets unpredictable versions + +**Instead**: Always reinstall with explicit `--version` to fix workload issues. + +--- + +## Java JDK (Microsoft OpenJDK ONLY) + +**CRITICAL: Only Microsoft Build of OpenJDK is supported.** Other JDK vendors (Oracle, Azul, Amazon Corretto, Temurin, etc.) are NOT supported for .NET MAUI development. + +> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated in a future Android workload release. + +See `microsoft-openjdk.md` for detection paths, identification, and JAVA_HOME guidance. + +For installation instructions, see the official docs: https://learn.microsoft.com/en-us/java/openjdk/install + +After installing, verify it is Microsoft OpenJDK: +```bash +# MUST show "Microsoft" in output +java -version +``` + +--- + +## Android SDK + +### Detecting Existing Android SDK + +```bash +# Check common environment variables +echo $ANDROID_HOME +echo $ANDROID_SDK_ROOT + +# Common SDK locations: +# macOS: ~/Library/Android/sdk +# Linux: ~/Android/Sdk +# Windows: %LOCALAPPDATA%\Android\Sdk + +# Check if sdkmanager is available +# macOS/Linux +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --version + +# Windows +%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin\sdkmanager.bat --version +``` + +### Installing Android SDK Command-Line Tools + +If no Android SDK exists, download the command-line tools: + +1. Download from: https://developer.android.com/studio#command-line-tools-only +2. Extract to your SDK root: + +```bash +# macOS/Linux +export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk" # macOS +# export ANDROID_SDK_ROOT="$HOME/Android/Sdk" # Linux +mkdir -p "$ANDROID_SDK_ROOT/cmdline-tools" +# Extract downloaded zip, move contents to: +# $ANDROID_SDK_ROOT/cmdline-tools/latest/ +``` + +```powershell +# Windows +$env:ANDROID_SDK_ROOT = "$env:LOCALAPPDATA\Android\Sdk" +New-Item -ItemType Directory -Force -Path "$env:ANDROID_SDK_ROOT\cmdline-tools" +# Extract downloaded zip, move contents to: +# $env:ANDROID_SDK_ROOT\cmdline-tools\latest\ +``` + +### Install Required Packages with sdkmanager + +Get exact versions from WorkloadDependencies.json (`androidsdk.packages`, `androidsdk.buildToolsVersion`, `androidsdk.apiLevel`). + +```bash +# macOS/Linux +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platform-tools" +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "build-tools;$BUILD_TOOLS_VERSION" +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-$API_LEVEL" +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "cmdline-tools;$CMDLINE_TOOLS_VERSION" + +# Accept all licenses +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses +``` + +```powershell +# Windows +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "platform-tools" +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "build-tools;$BUILD_TOOLS_VERSION" +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "platforms;android-$API_LEVEL" +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "cmdline-tools;$CMDLINE_TOOLS_VERSION" + +# Accept all licenses +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --licenses +``` + +### Verify Android SDK + +```bash +# Check ADB +adb --version + +# List installed packages (macOS/Linux) +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed + +# List installed packages (Windows) +# & "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --list_installed +``` diff --git a/.agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/.agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md new file mode 100644 index 0000000000..9d17c46867 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md @@ -0,0 +1,111 @@ +# Microsoft OpenJDK Requirements + +.NET MAUI requires **Microsoft Build of OpenJDK** for Android development. Other JDK distributions (Oracle, Azul, Amazon Corretto, etc.) are **not supported**. + +> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated in a future Android workload release. If WorkloadDependencies suggests ≤21, use 21. If it suggests >21, use that value. + +## Why Microsoft OpenJDK Only? + +- Tested and validated with .NET MAUI toolchain +- Consistent behavior across all platforms +- Long-term support with security updates +- Official recommendation from Microsoft documentation + +## Identifying Microsoft OpenJDK + +Run `java -version`. Microsoft OpenJDK output contains `Microsoft` in the runtime line: + +``` +openjdk version "17.0.14" 2025-01-21 LTS +OpenJDK Runtime Environment Microsoft-XXXXXXX (build 17.0.14+7-LTS) +OpenJDK 64-Bit Server VM Microsoft-XXXXXXX (build 17.0.14+7-LTS, mixed mode, sharing) +``` + +If the output does NOT contain "Microsoft", the wrong JDK is installed or selected. + +## Known Installation Paths + +These paths are useful for detecting whether Microsoft OpenJDK is already installed. + +### macOS + +``` +/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home +``` + +Detection: +```bash +ls -d /Library/Java/JavaVirtualMachines/microsoft-*.jdk 2>/dev/null +/usr/libexec/java_home -V 2>&1 | grep -i microsoft +``` + +### Windows + +``` +C:\Program Files\Microsoft\jdk-{VERSION}\ +``` + +Registry: `HKLM\SOFTWARE\Microsoft\JDK\{VERSION}` + +Detection: +```powershell +Get-ChildItem "C:\Program Files\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue +java -version 2>&1 | Select-String "Microsoft" +``` + +### Linux + +``` +/usr/lib/jvm/msopenjdk-{VERSION}/ +``` + +Detection: +```bash +ls -d /usr/lib/jvm/msopenjdk-* 2>/dev/null +java -version 2>&1 | grep -i "Microsoft" +``` + +--- + +## Installation + +For installation instructions, refer to the official Microsoft documentation: + +- [Microsoft OpenJDK Installation Guide](https://learn.microsoft.com/en-us/java/openjdk/install) +- [Microsoft OpenJDK Download](https://learn.microsoft.com/en-us/java/openjdk/download) + +--- + +## JAVA_HOME Guidance + +**JAVA_HOME is NOT required.** .NET MAUI tools auto-detect JDK installations. + +| State | OK? | Action | +|-------|-----|--------| +| Not set | ✅ | None needed, auto-detection works | +| Set to Microsoft JDK path | ✅ | None needed | +| Set to non-Microsoft JDK | ❌ | Unset it or point to Microsoft JDK | + +To unset: +```bash +# macOS/Linux +unset JAVA_HOME + +# Windows PowerShell +Remove-Item Env:JAVA_HOME +``` + +### Multiple JDKs Installed + +1. Run `java -version` and check for "Microsoft" in output +2. If wrong vendor and `JAVA_HOME` is set → unset it or point to Microsoft JDK path +3. If wrong vendor and `JAVA_HOME` is NOT set → the non-Microsoft JDK may be first in PATH; install Microsoft JDK and it should take precedence +4. Restart terminal after changes + +--- + +## Official Resources + +- [Microsoft OpenJDK Installation Guide](https://learn.microsoft.com/en-us/java/openjdk/install) +- [Microsoft OpenJDK Download](https://learn.microsoft.com/en-us/java/openjdk/download) +- [Microsoft OpenJDK GitHub](https://github.com/microsoft/openjdk) diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md new file mode 100644 index 0000000000..a12a8bde56 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md @@ -0,0 +1,36 @@ +# Linux Platform Requirements + +⚠️ **Linux has limited support** - Android targets only. + +## Required Components + +| Component | Requirement | Notes | +|-----------|-------------|-------| +| .NET SDK | Active support | Query releases-index.json | +| Java JDK | Per WorkloadDependencies | Microsoft OpenJDK **only** | +| Android SDK | Per WorkloadDependencies | Use packages array | + +## Required Workloads + +| Workload | Required | Purpose | +|----------|----------|---------| +| `maui-android` | ✅ Yes | MAUI for Android | +| `android` | ✅ Yes | Android targets | + +**Important**: Use `maui-android` NOT `maui` on Linux. The `maui` workload is a meta-workload that includes iOS/Mac dependencies which won't install on Linux. + +## Limitations + +- ❌ No iOS support (requires macOS) +- ❌ No Mac Catalyst support (requires macOS) +- ❌ No Windows support (requires Windows) + +## Android Development + +| Component | Source | Notes | +|-----------|--------|-------| +| Java JDK | `jdk.version` from WorkloadDependencies | Microsoft OpenJDK **only** | +| Android SDK | `androidsdk` from WorkloadDependencies | Use packages array | +| Platform Tools | `androidsdk.packages` | ADB, fastboot | +| Build Tools | `androidsdk.buildToolsVersion` | AAPT2, dx | +| KVM | Enabled | For emulator acceleration | diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md new file mode 100644 index 0000000000..250a53bf77 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md @@ -0,0 +1,36 @@ +# macOS Platform Requirements + +## Required Components + +| Component | Requirement | Notes | +|-----------|-------------|-------| +| macOS | Recent version | ARM64 or Intel | +| .NET SDK | Active support | Query releases-index.json for latest | +| Xcode | Per WorkloadDependencies | From [Apple Developer Downloads](https://developer.apple.com/download/all/) | +| Command Line Tools | Match Xcode | `xcode-select --install` | + +## Required Workloads + +| Workload | Required | Purpose | +|----------|----------|---------| +| `maui` | ✅ Yes | Core MAUI framework | +| `android` | ✅ Yes | Android targets | +| `ios` | ✅ Yes | iOS targets | +| `maccatalyst` | Recommended | Mac Catalyst targets | + +## Android Development + +| Component | Source | Notes | +|-----------|--------|-------| +| Java JDK | `jdk.version` from WorkloadDependencies | Microsoft OpenJDK **only** | +| Android SDK | `androidsdk` from WorkloadDependencies | Use packages array | +| Platform Tools | `androidsdk.packages` | ADB, fastboot | +| Build Tools | `androidsdk.buildToolsVersion` | AAPT2, dx | + +## iOS/macOS Development + +| Component | Source | Notes | +|-----------|--------|-------| +| Xcode | `xcode.version` from WorkloadDependencies | From iOS workload manifest | +| iOS SDK | `sdk.version` from WorkloadDependencies | Bundled with Xcode | +| iOS Simulator | Any | At least one device | diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md new file mode 100644 index 0000000000..09514a3f09 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md @@ -0,0 +1,35 @@ +# Windows Platform Requirements + +## Required Components + +| Component | Requirement | Notes | +|-----------|-------------|-------| +| Windows | 10 or later | 64-bit required | +| .NET SDK | Active support | Query releases-index.json for latest | +| Windows App SDK | Current | Required for WinUI 3 / Windows targets | + +## Required Workloads + +| Workload | Required | Purpose | +|----------|----------|---------| +| `maui` or `maui-windows` | ✅ Yes | Core MAUI framework | +| `android` | ✅ Yes | Android targets | +| `ios` | Optional | iOS targets (requires Mac build host) | +| `maccatalyst` | Optional | Mac Catalyst (requires Mac build host) | + +## Android Development + +| Component | Source | Notes | +|-----------|--------|-------| +| Java JDK | `jdk.version` from WorkloadDependencies | Microsoft OpenJDK **only** | +| Android SDK | `androidsdk` from WorkloadDependencies | Use packages array | +| Android Emulator | Latest | With HAXM or Hyper-V | +| Platform Tools | `androidsdk.packages` | ADB, fastboot | +| Build Tools | `androidsdk.buildToolsVersion` | AAPT2, dx | + +## Windows App Development + +| Component | Requirement | Notes | +|-----------|-------------|-------| +| Windows App SDK | Current | Required for WinUI 3 | +| Windows SDK | Recent | Windows 10+ SDK | diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md b/.agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md new file mode 100644 index 0000000000..54fdb00871 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md @@ -0,0 +1,79 @@ +# macOS Troubleshooting + +## Xcode Issues + +### "xcode-select: error: no developer tools found" + +**Solution**: +```bash +xcode-select --install +``` + +### "Xcode not found at expected location" + +**Solution**: +```bash +# List Xcode installations +ls -d /Applications/Xcode*.app 2>/dev/null + +# Set active Xcode +sudo xcode-select -s /Applications/Xcode.app/Contents/Developer +``` + +### "Unable to boot simulator" + +**Causes & Solutions**: + +1. **No simulators installed**: + ```bash + xcrun simctl list devices available + xcrun simctl create "iPhone 16" "com.apple.CoreSimulator.SimDeviceType.iPhone-16" + ``` + +2. **Simulator runtime not installed**: + - Download an iOS runtime via `xcodebuild -downloadPlatform iOS` or from Xcode → Settings → Platforms + +3. **Corrupted simulator**: + ```bash + xcrun simctl erase all + ``` + +### "Code signing error" + +**Cause**: Missing or invalid provisioning profile. + +**Solution**: +1. Open Xcode → Settings → Accounts +2. Add/refresh Apple Developer account +3. Download provisioning profiles + +--- + +## macOS Performance + +### Slow iOS simulator + +1. Close other resource-intensive apps +2. Use recent simulator device (not legacy) +3. Reduce debugger verbosity +4. Use physical device for performance testing + +--- + +## macOS Diagnostic Commands + +```bash +# Xcode info +xcodebuild -version +xcode-select -p + +# JDK detection (macOS-specific) +/usr/libexec/java_home -V + +# Android SDK location +echo $ANDROID_SDK_ROOT +# Default: ~/Library/Android/sdk + +# Logs +# ~/Library/Logs/Xamarin/ +``` diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md b/.agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md new file mode 100644 index 0000000000..5d75500a95 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md @@ -0,0 +1,34 @@ +# Windows Troubleshooting + +## Emulator Issues + +### Hyper-V conflict with Android Emulator + +**Cause**: HAXM and Hyper-V cannot coexist. + +**Solution**: +- Use Android Emulator Hypervisor Driver instead of HAXM +- Or disable Hyper-V: `bcdedit /set hypervisorlaunchtype off` + +--- + +## Windows Diagnostic Commands + +```powershell +# Windows SDK detection +Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue + +# JDK detection (Windows-specific) +Get-ChildItem "C:\Program Files\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue +java -version 2>&1 | Select-String "Microsoft" + +# Android SDK location +echo $env:ANDROID_SDK_ROOT +# Default: $env:LOCALAPPDATA\Android\Sdk + +# Android SDK list installed (Windows) +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --list_installed + +# Logs +# %LOCALAPPDATA%\Xamarin\Logs\ +``` diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting.md b/.agents/skills/dotnet-maui-doctor/references/troubleshooting.md new file mode 100644 index 0000000000..90c5ec74e7 --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/troubleshooting.md @@ -0,0 +1,316 @@ +# Troubleshooting .NET MAUI Environment Issues + +Common problems and solutions when setting up or using .NET MAUI. + +**See also platform-specific troubleshooting:** +- macOS: `troubleshooting-macos.md` +- Windows: `troubleshooting-windows.md` + +## .NET SDK Issues + +### "dotnet: command not found" + +**Cause**: .NET SDK not installed or not in PATH. + +**Solution**: +```bash +# Check if dotnet exists +which dotnet + +# macOS/Linux - Add to PATH if installed via dotnet-install script +export PATH="$PATH:$HOME/.dotnet" +``` + +If not installed, see: https://dotnet.microsoft.com/download + +### "The required workload is not installed" + +**Cause**: MAUI workload not installed. + +**Solution**: +```bash +dotnet workload install maui --version $WORKLOAD_VERSION +``` + +### "Workload version mismatch" + +**Cause**: Workloads from different SDK versions or incomplete installation. + +**Solution**: Reinstall workloads with explicit version: +```bash +# First, find the correct workload set version for your SDK +# Query NuGet APIs (see workload-dependencies-discovery.md) + +# Then reinstall with explicit version +dotnet workload install maui android ios maccatalyst --version $WORKLOAD_VERSION +``` + +**Note**: Avoid `dotnet workload update` or `dotnet workload repair` as they can cause version inconsistencies. + +### SDK version conflict with global.json + +**Cause**: Project requires specific SDK version not installed. + +**Solution**: +```bash +# Check required version +cat global.json + +# Install specific version +curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --version X.Y.Z +``` + +--- + +## Java JDK Issues + +**IMPORTANT: Only Microsoft Build of OpenJDK is supported.** Other JDK vendors (Oracle, Azul, Amazon Corretto, Temurin) are NOT supported for .NET MAUI development. + +See `microsoft-openjdk.md` for complete installation paths by platform. + +### "JAVA_HOME is not set" + +**This is usually NOT a problem.** The .NET MAUI toolchain auto-detects JDK installations without needing `JAVA_HOME`. + +**When JAVA_HOME matters:** +- ❌ `JAVA_HOME` is set but points to a **non-Microsoft JDK** → Fix by unsetting or pointing to Microsoft JDK +- ✅ `JAVA_HOME` is not set → Fine, tools will auto-detect +- ✅ `JAVA_HOME` points to Microsoft JDK → Fine + +**Solution (only if JAVA_HOME is set to wrong JDK):** +```bash +# Option 1: Unset JAVA_HOME (let tools auto-detect) +unset JAVA_HOME + +# Option 2: Point to Microsoft JDK (macOS) +export JAVA_HOME=/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home + +# Option 2: Point to Microsoft JDK (Linux) +export JAVA_HOME=/usr/lib/jvm/msopenjdk-17 + +# Option 2: Point to Microsoft JDK (Windows PowerShell) +$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-17.0.14+7" +# Or remove it: Remove-Item Env:JAVA_HOME +``` + +### "Unsupported Java version" or "Wrong JDK vendor" + +**Cause**: JDK version outside required range OR non-Microsoft JDK installed. + +> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated. + +**Solution**: Install Microsoft OpenJDK 21 using the [official installation guide](https://learn.microsoft.com/en-us/java/openjdk/install). + +### Non-Microsoft JDK detected + +**Cause**: Oracle, Azul, Corretto, or other non-Microsoft JDK is installed and selected. + +**How to identify**: Run `java -version` - if output does NOT contain "Microsoft", wrong JDK is selected. + +**Solution**: +1. Install Microsoft OpenJDK 21 (see commands above) +2. Set `JAVA_HOME` to Microsoft JDK path: + - macOS: `/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home` + - Windows: `C:\Program Files\Microsoft\jdk-{VERSION}\` + - Linux: `/usr/lib/jvm/msopenjdk-{VERSION}` +3. Optionally uninstall the non-Microsoft JDK + +### Multiple JDKs installed, wrong one selected + +**Solution**: +```bash +# macOS - find Microsoft JDK +/usr/libexec/java_home -V 2>&1 | grep -i microsoft + +# Linux - set Microsoft as default +sudo update-java-alternatives --set msopenjdk-21-amd64 +``` + +--- + +## Android SDK Issues + +### "Android SDK not found" + +**Cause**: SDK not installed or path not configured. + +**Solution**: +```bash +# Check environment variables +echo $ANDROID_HOME +echo $ANDROID_SDK_ROOT + +# Common SDK locations: +# macOS: ~/Library/Android/sdk +# Linux: ~/Android/Sdk +# Windows: %LOCALAPPDATA%\Android\Sdk + +# If no SDK found, download command-line tools from: +# https://developer.android.com/studio#command-line-tools-only +``` + +### "Failed to find Build Tools" + +**Cause**: Required build-tools package not installed. + +**Solution**: +```bash +# Get build tools version from WorkloadDependencies.json (androidsdk.buildToolsVersion) + +# Use sdkmanager (macOS/Linux) +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "build-tools;$BUILD_TOOLS_VERSION" + +# Windows +# & "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "build-tools;$BUILD_TOOLS_VERSION" +``` + +### "License not accepted" + +**Cause**: Android SDK licenses not accepted. + +**Solution**: +```bash +# macOS/Linux +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses + +# Windows +# & "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --licenses +``` + +### "Platform not found: android-XX" + +**Cause**: Target platform not installed. + +**Solution**: +```bash +# Get required API level from WorkloadDependencies.json (androidsdk.apiLevel) + +# macOS/Linux +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-$API_LEVEL" + +# Windows +# & "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" "platforms;android-$API_LEVEL" +``` + +### Emulator won't start + +**Causes & Solutions**: + +1. **HAXM/KVM not enabled**: + ```bash + # Linux - check KVM + kvm-ok + + # Enable KVM + sudo modprobe kvm + ``` + +2. **Insufficient disk space**: + - Clear AVD cache: `~/.android/avd/` + +See also: `troubleshooting-windows.md` for Hyper-V conflicts. + +--- + +## Build Errors + +### "The target framework 'net10.0-android' is not available" + +**Cause**: Android workload not installed for this SDK. + +**Solution**: +```bash +dotnet workload install android --version $WORKLOAD_VERSION +``` + +### "Could not find android.jar" + +**Cause**: Android platform not installed. + +**Solution**: +```bash +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-35" +``` + +### "MSB4019: The imported project was not found" + +**Cause**: Workload not properly installed. + +**Solution**: Reinstall with explicit version: +```bash +# Get correct workload version for your SDK band from NuGet APIs, then: +dotnet workload install maui --version $WORKLOAD_VERSION +``` + +### "NETSDK1147: To build this project, the following workloads must be installed" + +**Solution**: Install the listed workloads with explicit version: +```bash +dotnet workload install [workload-name] --version $WORKLOAD_VERSION +``` + +--- + +## Performance Issues + +### Slow builds + +**Solutions**: +1. Enable incremental builds (default) +2. Use Hot Reload during development +3. Build only necessary platforms: + ```bash + dotnet build -f net10.0-android + ``` + +### Slow Android emulator + +**Solutions**: +1. Enable hardware acceleration (HAXM/KVM/Hyper-V) +2. Use x86_64 system image (not ARM on Intel) +3. Increase emulator RAM in AVD settings +4. Use physical device for testing + +--- + +## Environment Variable Reference + +| Variable | Purpose | Required | Notes | +|----------|---------|----------|-------| +| `JAVA_HOME` | JDK location | No | Only problematic if set to non-Microsoft JDK | +| `ANDROID_HOME` | Android SDK location | No | Auto-detected | +| `ANDROID_SDK_ROOT` | Android SDK location | No | Alternative to ANDROID_HOME | +| `DOTNET_ROOT` | .NET SDK location | No | Usually auto-detected | +| `PATH` | Must include dotnet | Yes | Required for CLI access | + +**Key point about JAVA_HOME:** +- ✅ Not set → Fine, tools auto-detect Microsoft JDK +- ✅ Set to Microsoft JDK path → Fine +- ❌ Set to non-Microsoft JDK → Problem! Unset or fix it + +**Note**: The .NET MAUI toolchain auto-detects most paths. Only set these manually if auto-detection fails or wrong JDK is being selected. + +--- + +## Getting Help + +### Diagnostic Commands + +```bash +# Full .NET info +dotnet --info + +# Workload status +dotnet workload list + +# JDK info +java -version +``` + +See platform-specific troubleshooting files for additional diagnostic commands. + +### Resources + +- [.NET MAUI GitHub Issues](https://github.com/dotnet/maui/issues) +- [Stack Overflow - maui tag](https://stackoverflow.com/questions/tagged/maui) +- [.NET MAUI Documentation](https://learn.microsoft.com/en-us/dotnet/maui/) diff --git a/.agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md b/.agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md new file mode 100644 index 0000000000..a8766fcf5b --- /dev/null +++ b/.agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md @@ -0,0 +1,191 @@ +# Workload Dependencies Discovery + +This reference describes how to discover authoritative version requirements from NuGet APIs. All JDK, Android SDK, and Xcode requirements come from WorkloadDependencies.json - never hardcode versions. + +## Workload Aliases + +| Alias | Full ID | +|-------|---------| +| ios | microsoft.net.sdk.ios | +| android | microsoft.net.sdk.android | +| maccatalyst | microsoft.net.sdk.maccatalyst | +| macos | microsoft.net.sdk.macos | +| tvos | microsoft.net.sdk.tvos | +| maui | microsoft.net.sdk.maui | + +--- + +## Discovery Process + +### Step 1: Get Latest SDK Version + +```bash +curl -s "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" | \ + jq '.["releases-index"][] | select(.["channel-version"]=="{MAJOR}.0")' +``` + +Response fields: +| Field | Description | +|-------|-------------| +| `channel-version` | Major.minor (e.g., "10.0") | +| `latest-sdk` | Current stable SDK version | +| `support-phase` | "active", "maintenance", "eol" | + +Extract `latest-sdk` and derive SDK band: +- `10.0.102` → band `10.0.100` (hundreds digit) +- `10.0.205` → band `10.0.200` + +### Step 2: Find Workload Set Package + +First, discover the NuGet search endpoint from the service index: +```bash +# Get the SearchQueryService URL from the NuGet v3 service index +NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ + jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) +``` + +Then search for the workload set package: +```bash +curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.{MAJOR}.0&prerelease=false&semVerLevel=2.0.0" +``` + +Filter results: +- Match `Microsoft.NET.Workloads.{major}.{band}` (e.g., `Microsoft.NET.Workloads.10.0.100`) +- Exclude `.Msi.*` packages +- Pick highest version + +**Version conversion**: NuGet `10.102.0` → CLI `10.0.102` +``` +parts = nugetVersion.split('.') +cliVersion = parts[0] + ".0." + parts[1] +``` + +### Step 3: Download Workload Set Manifest + +```bash +curl -o workloadset.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.{band}/{version}/microsoft.net.workloads.{band}.{version}.nupkg" +unzip -p workloadset.nupkg data/microsoft.net.workloads.workloadset.json +``` + +Contents format: `"{workload_id}": "{manifestVersion}/{sdkBand}"` + +Example: +```json +{ + "microsoft.net.sdk.android": "35.0.50/9.0.100", + "microsoft.net.sdk.ios": "26.2.10191/10.0.100", + "microsoft.net.sdk.maui": "10.0.10/10.0.100" +} +``` + +### Step 4: Download Workload Manifest + +Build package id: `{WorkloadId}.Manifest-{sdkBand}` + +Examples: +- `Microsoft.NET.Sdk.iOS.Manifest-10.0.100` +- `Microsoft.NET.Sdk.Android.Manifest-9.0.100` + +```bash +curl -o manifest.nupkg "https://api.nuget.org/v3-flatcontainer/{packageid}/{version}/{packageid}.{version}.nupkg" +unzip -p manifest.nupkg data/WorkloadDependencies.json +``` + +### Step 5: Parse WorkloadDependencies.json + +**Android workload** (`microsoft.net.sdk.android`): +```json +{ + "microsoft.net.sdk.android": { + "jdk": { + "version": "[17.0,22.0)", + "recommendedVersion": "17.0.14" + }, + "androidsdk": { + "packages": ["build-tools;35.0.0", "platform-tools", "platforms;android-35", "cmdline-tools;13.0"], + "apiLevel": "35", + "buildToolsVersion": "35.0.0", + "cmdLineToolsVersion": "13.0" + } + } +} +``` + +**iOS workload** (`microsoft.net.sdk.ios`): +```json +{ + "microsoft.net.sdk.ios": { + "xcode": { + "version": "[26.2,)", + "recommendedVersion": "26.2" + }, + "sdk": { + "version": "26.2" + } + } +} +``` + +### Version Range Notation + +| Notation | Meaning | +|----------|---------| +| `[17.0,22.0)` | >= 17.0 AND < 22.0 | +| `[26.2,)` | >= 26.2 (no upper bound) | + +Brackets: `[` = inclusive, `(` = exclusive + +--- + +## Complete Example + +**Goal**: Find requirements for .NET 10 + +```bash +# Step 1: Get SDK info +curl -s "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" | \ + jq '.["releases-index"][] | select(.["channel-version"]=="10.0") | .["latest-sdk"]' +# Result: "10.0.102" → band "10.0.100" + +# Step 2: Discover NuGet search endpoint and find workload set +NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ + jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) +curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.10.0&prerelease=false" | \ + jq '.data[] | select(.id=="Microsoft.NET.Workloads.10.0.100") | {id, version}' +# Result: { "id": "Microsoft.NET.Workloads.10.0.100", "version": "10.102.0" } +# CLI version: 10.0.102 + +# Step 3: Download workload set manifest +curl -so workloadset.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.10.0.100/10.102.0/microsoft.net.workloads.10.0.100.10.102.0.nupkg" +unzip -p workloadset.nupkg data/microsoft.net.workloads.workloadset.json | jq '."microsoft.net.sdk.android"' +# Result: "35.0.50/9.0.100" + +# Step 4: Download Android manifest +curl -so android.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.sdk.android.manifest-9.0.100/35.0.50/microsoft.net.sdk.android.manifest-9.0.100.35.0.50.nupkg" +unzip -p android.nupkg data/WorkloadDependencies.json | jq '.["microsoft.net.sdk.android"]' +``` + +**Result**: Authoritative JDK, Android SDK, and Xcode requirements from live NuGet data. + +--- + +## NuGet API Reference + +| Operation | Endpoint | +|-----------|----------| +| .NET releases | `https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json` | +| NuGet service index | `https://api.nuget.org/v3/index.json` | +| Download package | `https://api.nuget.org/v3-flatcontainer/{id}/{version}/{id}.{version}.nupkg` | + +**Discover the search endpoint** from the service index by filtering for `SearchQueryService` type. Do not hardcode search URLs — they are regional and may change. + +**Important**: Package IDs must be lowercase in download URLs. + +--- + +## Best Practices + +- **ALWAYS** fetch live data from NuGet APIs +- **NEVER** hardcode version requirements +- **ALWAYS** include SDK band with manifest versions +- Show exact URLs used for transparency From cd678720c053d70ff2e4bb32ad80454506abcc5b Mon Sep 17 00:00:00 2001 From: redth Date: Thu, 12 Feb 2026 16:06:35 -0500 Subject: [PATCH 02/18] MAUI doesn't quite yet support dotnet run --- .agents/skills/dotnet-maui-doctor/SKILL.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.agents/skills/dotnet-maui-doctor/SKILL.md b/.agents/skills/dotnet-maui-doctor/SKILL.md index c4216f7245..429e835190 100644 --- a/.agents/skills/dotnet-maui-doctor/SKILL.md +++ b/.agents/skills/dotnet-maui-doctor/SKILL.md @@ -130,14 +130,14 @@ If the build succeeds, the environment is verified. If it fails, use the error o ### Run Verification (Optional — Ask User First) -As of the latest .NET 10 SDK (10.0.103), `dotnet run` works for MAUI projects. After a successful build, **ask the user** if they want to launch the app on a target platform to verify end-to-end: +After a successful build, **ask the user** if they want to launch the app on a target platform to verify end-to-end: ```bash # Replace net10.0 with the current major .NET version -dotnet run -f net10.0-android -dotnet run -f net10.0-ios # macOS only -dotnet run -f net10.0-maccatalyst # macOS only -dotnet run -f net10.0-windows # Windows only +dotnet build -t:Run -f net10.0-android +dotnet build -t:Run -f net10.0-ios # macOS only +dotnet build -t:Run -f net10.0-maccatalyst # macOS only +dotnet build -t:Run -f net10.0-windows # Windows only ``` Only run the target frameworks relevant to the user's platform and intent. This step deploys to an emulator/simulator/device, so confirm with the user before proceeding. From 37b9c157971cfb1716d345d9af8da0b567e5173b Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 4 Mar 2026 16:44:04 +0100 Subject: [PATCH 03/18] Add dotnet-maui plugin and dotnet-maui-doctor skill Introduce the dotnet-maui plugin and move the dotnet-maui-doctor skill under plugins/ layout. Update marketplace, CODEOWNERS, and README accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/CODEOWNERS | 4 + .github/plugin/marketplace.json | 5 ++ README.md | 1 + plugins/dotnet-maui/plugin.json | 6 ++ .../skills/dotnet-maui-doctor/SKILL.md | 43 +++++++++- .../references/installation-commands-macos.md | 0 .../installation-commands-windows.md | 0 .../references/installation-commands.md | 0 .../references/microsoft-openjdk.md | 0 .../references/platform-requirements-linux.md | 0 .../references/platform-requirements-macos.md | 0 .../platform-requirements-windows.md | 0 .../references/troubleshooting-macos.md | 0 .../references/troubleshooting-windows.md | 0 .../references/troubleshooting.md | 0 .../workload-dependencies-discovery.md | 83 +++++++++++++++++++ .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 21 +++++ 17 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 plugins/dotnet-maui/plugin.json rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/SKILL.md (70%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/installation-commands-macos.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/installation-commands-windows.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/installation-commands.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/microsoft-openjdk.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/platform-requirements-linux.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/platform-requirements-macos.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/platform-requirements-windows.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/troubleshooting-macos.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/troubleshooting-windows.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/troubleshooting.md (100%) rename {.agents => plugins/dotnet-maui}/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md (61%) create mode 100644 tests/dotnet-maui/dotnet-maui-doctor/eval.yaml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 68b40a1e16..3ccf489553 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -54,3 +54,7 @@ # dotnet-data (data access, Entity Framework) /plugins/dotnet-data/skills/optimizing-ef-core-queries/ @dotnet/efteam /tests/dotnet-data/optimizing-ef-core-queries/ @dotnet/efteam + +# dotnet-maui +/plugins/dotnet-maui/ @Redth @jfversluis +/tests/dotnet-maui/ @Redth @jfversluis diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 2177a87904..02a140fe07 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -28,6 +28,11 @@ "name": "dotnet-upgrade", "source": "./plugins/dotnet-upgrade", "description": "Skills for migrating and upgrading .NET projects across framework versions, language features, and compatibility targets." + }, + { + "name": "dotnet-maui", + "source": "./plugins/dotnet-maui", + "description": "Skills for .NET MAUI development: environment setup, diagnostics, and troubleshooting." } ] } diff --git a/README.md b/README.md index 87bc7c85b3..d487802a71 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ This repository contains the .NET team's curated set of core skills and custom a | [dotnet-diag](plugins/dotnet-diag/) | Skills for .NET performance investigations, debugging, and incident analysis. | | [dotnet-msbuild](plugins/dotnet-msbuild/) | Comprehensive MSBuild and .NET build skills: failure diagnosis, performance optimization, code quality, and modernization. | | [dotnet-upgrade](plugins/dotnet-upgrade/) | Skills for migrating and upgrading .NET projects across framework versions, language features, and compatibility targets. | +| [dotnet-maui](plugins/dotnet-maui/) | Skills for .NET MAUI development: environment setup, diagnostics, and troubleshooting. | ## Installation diff --git a/plugins/dotnet-maui/plugin.json b/plugins/dotnet-maui/plugin.json new file mode 100644 index 0000000000..0160aa99f8 --- /dev/null +++ b/plugins/dotnet-maui/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "dotnet-maui", + "version": "0.1.0", + "description": "Skills for .NET MAUI development: environment setup, diagnostics, and troubleshooting.", + "skills": "./skills/" +} diff --git a/.agents/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md similarity index 70% rename from .agents/skills/dotnet-maui-doctor/SKILL.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index 429e835190..c68d2002ed 100644 --- a/.agents/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -1,16 +1,48 @@ --- name: dotnet-maui-doctor -description: Diagnoses and fixes .NET MAUI development environment issues. Validates .NET SDK, workloads, Java JDK, Android SDK, Xcode, and Windows SDK. All version requirements discovered dynamically from NuGet WorkloadDependencies.json - never hardcoded. Use when: setting up MAUI development, build errors mentioning SDK/workload/JDK/Android, "Android SDK not found", "Java version" errors, "Xcode not found", environment verification after updates, or any MAUI toolchain issues. Works on macOS, Windows, and Linux. +description: >- + Diagnoses and fixes .NET MAUI development environment issues. Validates .NET SDK, + workloads, Java JDK, Android SDK, Xcode, and Windows SDK. All version requirements + discovered dynamically from NuGet WorkloadDependencies.json — never hardcoded. + Use when: setting up MAUI development, build errors mentioning SDK/workload/JDK/Android, + "Android SDK not found", "Java version" errors, "Xcode not found", environment verification + after updates, or any MAUI toolchain issues. Do not use for: non-MAUI .NET projects, + Xamarin.Forms apps, runtime app crashes unrelated to environment setup, or app store + publishing issues. Works on macOS, Windows, and Linux. --- # .NET MAUI Doctor Validate and fix .NET MAUI development environments. All version requirements are discovered dynamically from NuGet APIs — never hardcode versions. +## When to Use + +- Setting up a new .NET MAUI development environment +- Build errors mentioning missing SDKs, workloads, JDK, or Android components +- Errors like "Android SDK not found", "Java version", or "Xcode not found" +- Verifying environment health after SDK or OS updates + +## When Not to Use + +- Non-MAUI .NET projects (use standard .NET SDK troubleshooting instead) +- Xamarin.Forms apps (different toolchain and workload requirements) +- Runtime app crashes unrelated to environment setup +- App store publishing or signing issues +- IDE-specific issues (Visual Studio or VS Code configuration) + ## Important: .NET Version Currency Your training data may be outdated regarding .NET versions. .NET ships new major releases annually (November). Always check the releases-index.json (Task 2) to discover the **latest active major release** — do not assume your training data reflects the current version. For example, if you know about .NET 9.0 but the releases index shows .NET 10.0 as active, use .NET 10.0. +## Inputs + +- A development machine running macOS, Windows, or Linux +- Shell access (Bash on macOS/Linux, PowerShell on Windows) +- Internet access for NuGet API queries and SDK downloads +- Admin/sudo access may be required for installing SDKs and workloads +- **Bash prerequisites**: `curl`, `jq`, and `unzip` (macOS/Linux) +- **PowerShell prerequisites**: `Invoke-RestMethod` and `System.IO.Compression` (built-in on Windows) + ## Behavior - Run through ALL tasks autonomously @@ -142,6 +174,15 @@ dotnet build -t:Run -f net10.0-windows # Windows only Only run the target frameworks relevant to the user's platform and intent. This step deploys to an emulator/simulator/device, so confirm with the user before proceeding. +## Common Pitfalls + +- **`maui` vs `maui-android` workload**: On Linux, the `maui` meta-workload is not available — use `maui-android` instead. On macOS/Windows, `maui` installs all platform workloads. +- **`workload update` / `workload repair`**: Never use these commands. Always install workloads with an explicit `--version` flag to ensure version consistency. +- **Non-Microsoft JDK**: Only Microsoft OpenJDK is supported. Other distributions (Oracle, Adoptium, Azul) will cause build failures even if the version is correct. +- **Hardcoded versions**: Never hardcode SDK, workload, or dependency versions. Always discover them dynamically from the NuGet APIs (see Task 4). +- **Android SDK `sdkmanager` on Windows**: Use `sdkmanager.bat`, not `sdkmanager`, on Windows. +- **Stale training data**: LLM training data may reference outdated .NET versions. Always check the releases-index.json to discover the current active release. + ## References - `references/workload-dependencies-discovery.md` — NuGet API discovery process diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/installation-commands-macos.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/installation-commands-windows.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md diff --git a/.agents/skills/dotnet-maui-doctor/references/installation-commands.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/installation-commands.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md diff --git a/.agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/microsoft-openjdk.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-linux.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/platform-requirements-linux.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-linux.md diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-macos.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/platform-requirements-macos.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-macos.md diff --git a/.agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-windows.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/platform-requirements-windows.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/platform-requirements-windows.md diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-macos.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/troubleshooting-macos.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-macos.md diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/troubleshooting-windows.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md diff --git a/.agents/skills/dotnet-maui-doctor/references/troubleshooting.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md similarity index 100% rename from .agents/skills/dotnet-maui-doctor/references/troubleshooting.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md diff --git a/.agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md similarity index 61% rename from .agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md rename to plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md index a8766fcf5b..e781c3bc85 100644 --- a/.agents/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md @@ -19,11 +19,18 @@ This reference describes how to discover authoritative version requirements from ### Step 1: Get Latest SDK Version +**Bash:** ```bash curl -s "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" | \ jq '.["releases-index"][] | select(.["channel-version"]=="{MAJOR}.0")' ``` +**PowerShell:** +```powershell +$releases = Invoke-RestMethod "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" +$releases.'releases-index' | Where-Object { $_.'channel-version' -eq '{MAJOR}.0' } +``` + Response fields: | Field | Description | |-------|-------------| @@ -38,17 +45,32 @@ Extract `latest-sdk` and derive SDK band: ### Step 2: Find Workload Set Package First, discover the NuGet search endpoint from the service index: + +**Bash:** ```bash # Get the SearchQueryService URL from the NuGet v3 service index NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) ``` +**PowerShell:** +```powershell +$serviceIndex = Invoke-RestMethod "https://api.nuget.org/v3/index.json" +$nugetSearchUrl = ($serviceIndex.resources | Where-Object { $_.'@type' -eq 'SearchQueryService' } | Select-Object -First 1).'@id' +``` + Then search for the workload set package: + +**Bash:** ```bash curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.{MAJOR}.0&prerelease=false&semVerLevel=2.0.0" ``` +**PowerShell:** +```powershell +Invoke-RestMethod "$nugetSearchUrl`?q=Microsoft.NET.Workloads.{MAJOR}.0&prerelease=false&semVerLevel=2.0.0" +``` + Filter results: - Match `Microsoft.NET.Workloads.{major}.{band}` (e.g., `Microsoft.NET.Workloads.10.0.100`) - Exclude `.Msi.*` packages @@ -62,11 +84,23 @@ cliVersion = parts[0] + ".0." + parts[1] ### Step 3: Download Workload Set Manifest +**Bash:** ```bash curl -o workloadset.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.{band}/{version}/microsoft.net.workloads.{band}.{version}.nupkg" unzip -p workloadset.nupkg data/microsoft.net.workloads.workloadset.json ``` +**PowerShell:** +```powershell +Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.{band}/{version}/microsoft.net.workloads.{band}.{version}.nupkg" -OutFile workloadset.nupkg +Add-Type -AssemblyName System.IO.Compression.FileSystem +$zip = [System.IO.Compression.ZipFile]::OpenRead("workloadset.nupkg") +$entry = $zip.Entries | Where-Object { $_.FullName -eq "data/microsoft.net.workloads.workloadset.json" } +$reader = [System.IO.StreamReader]::new($entry.Open()) +$reader.ReadToEnd() | ConvertFrom-Json +$reader.Dispose(); $zip.Dispose() +``` + Contents format: `"{workload_id}": "{manifestVersion}/{sdkBand}"` Example: @@ -86,11 +120,22 @@ Examples: - `Microsoft.NET.Sdk.iOS.Manifest-10.0.100` - `Microsoft.NET.Sdk.Android.Manifest-9.0.100` +**Bash:** ```bash curl -o manifest.nupkg "https://api.nuget.org/v3-flatcontainer/{packageid}/{version}/{packageid}.{version}.nupkg" unzip -p manifest.nupkg data/WorkloadDependencies.json ``` +**PowerShell:** +```powershell +Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/{packageid}/{version}/{packageid}.{version}.nupkg" -OutFile manifest.nupkg +$zip = [System.IO.Compression.ZipFile]::OpenRead("manifest.nupkg") +$entry = $zip.Entries | Where-Object { $_.FullName -eq "data/WorkloadDependencies.json" } +$reader = [System.IO.StreamReader]::new($entry.Open()) +$reader.ReadToEnd() | ConvertFrom-Json +$reader.Dispose(); $zip.Dispose() +``` + ### Step 5: Parse WorkloadDependencies.json **Android workload** (`microsoft.net.sdk.android`): @@ -141,6 +186,8 @@ Brackets: `[` = inclusive, `(` = exclusive **Goal**: Find requirements for .NET 10 +### Bash + ```bash # Step 1: Get SDK info curl -s "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" | \ @@ -165,6 +212,42 @@ curl -so android.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.sdk unzip -p android.nupkg data/WorkloadDependencies.json | jq '.["microsoft.net.sdk.android"]' ``` +### PowerShell + +```powershell +# Step 1: Get SDK info +$releases = Invoke-RestMethod "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json" +$sdkInfo = $releases.'releases-index' | Where-Object { $_.'channel-version' -eq '10.0' } +$latestSdk = $sdkInfo.'latest-sdk' +# Result: "10.0.102" → band "10.0.100" + +# Step 2: Discover NuGet search endpoint and find workload set +$serviceIndex = Invoke-RestMethod "https://api.nuget.org/v3/index.json" +$searchUrl = ($serviceIndex.resources | Where-Object { $_.'@type' -eq 'SearchQueryService' } | Select-Object -First 1).'@id' +$result = Invoke-RestMethod "$searchUrl`?q=Microsoft.NET.Workloads.10.0&prerelease=false" +$workloadSet = $result.data | Where-Object { $_.id -eq 'Microsoft.NET.Workloads.10.0.100' } +# Result: version "10.102.0", CLI version: 10.0.102 + +# Step 3: Download workload set manifest and extract +Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.10.0.100/10.102.0/microsoft.net.workloads.10.0.100.10.102.0.nupkg" -OutFile workloadset.nupkg +Add-Type -AssemblyName System.IO.Compression.FileSystem +$zip = [System.IO.Compression.ZipFile]::OpenRead("workloadset.nupkg") +$entry = $zip.Entries | Where-Object { $_.FullName -eq "data/microsoft.net.workloads.workloadset.json" } +$reader = [System.IO.StreamReader]::new($entry.Open()) +$manifest = $reader.ReadToEnd() | ConvertFrom-Json +$reader.Dispose(); $zip.Dispose() +$manifest.'microsoft.net.sdk.android' +# Result: "35.0.50/9.0.100" + +# Step 4: Download Android manifest and extract WorkloadDependencies +Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/microsoft.net.sdk.android.manifest-9.0.100/35.0.50/microsoft.net.sdk.android.manifest-9.0.100.35.0.50.nupkg" -OutFile android.nupkg +$zip = [System.IO.Compression.ZipFile]::OpenRead("android.nupkg") +$entry = $zip.Entries | Where-Object { $_.FullName -eq "data/WorkloadDependencies.json" } +$reader = [System.IO.StreamReader]::new($entry.Open()) +$reader.ReadToEnd() | ConvertFrom-Json +$reader.Dispose(); $zip.Dispose() +``` + **Result**: Authoritative JDK, Android SDK, and Xcode requirements from live NuGet data. --- diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml new file mode 100644 index 0000000000..7c85088bc4 --- /dev/null +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -0,0 +1,21 @@ +scenarios: + - name: "Plan MAUI Android setup on Linux" + prompt: "I'm on Linux and setting up .NET MAUI for Android. I can't run commands right now. Give me a step-by-step diagnostic and remediation plan that discovers exact SDK/workload/JDK/Android SDK requirements dynamically (no hardcoded versions)." + assertions: + - type: "output_contains" + value: "WorkloadDependencies.json" + - type: "output_contains" + value: "releases-index.json" + - type: "output_matches" + pattern: "maui-android" + - type: "output_contains" + value: "Microsoft Build of OpenJDK" + - type: "output_contains" + value: "dotnet workload" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Calls out Linux is Android-only and recommends maui-android (not maui)" + - "Uses releases-index.json and NuGet APIs to discover requirements (no hardcoded versions)" + - "Avoids recommending dotnet workload update/repair" + timeout: 120 From a93e775a6e4857fade5417b14d996d19c1748782 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 4 Mar 2026 17:08:16 +0100 Subject: [PATCH 04/18] Add comprehensive eval scenarios for dotnet-maui-doctor 10 scenarios covering: macOS/Linux/Windows setup, JDK vendor enforcement, workload update/repair guardrails, dynamic version discovery, JAVA_HOME misconception, Android SDK diagnosis, out-of-scope decline, and stale workload remediation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 225 +++++++++++++++++- 1 file changed, 215 insertions(+), 10 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index 7c85088bc4..39ee3b5ea6 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -1,21 +1,226 @@ scenarios: - - name: "Plan MAUI Android setup on Linux" - prompt: "I'm on Linux and setting up .NET MAUI for Android. I can't run commands right now. Give me a step-by-step diagnostic and remediation plan that discovers exact SDK/workload/JDK/Android SDK requirements dynamically (no hardcoded versions)." + - name: "Plan macOS MAUI setup with Xcode" + prompt: | + I have a clean macOS machine and want to start developing .NET MAUI apps + for iOS and Android. I can't run commands right now, but I need a complete + setup plan. Tell me exactly what I need to install, how to discover the + right versions, and how to verify everything works. assertions: - type: "output_contains" - value: "WorkloadDependencies.json" + value: "Xcode" + - type: "output_matches" + pattern: "(?i)apple developer|developer\\.apple\\.com" + - type: "output_not_matches" + pattern: "(?i)app\\s*store" + - type: "output_contains" + value: "Microsoft" + - type: "output_contains" + value: "--version" + - type: "output_matches" + pattern: "(?i)releases-index|WorkloadDependencies|NuGet" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Warns against installing Xcode from the Mac App Store and recommends Apple Developer Downloads" + - "Recommends the 'maui' workload (not 'maui-android') since this is macOS" + - "Specifies Microsoft OpenJDK as the only supported Java distribution" + - "Discovers versions dynamically via NuGet APIs rather than hardcoding them" + - "Uses --version flag when installing workloads" + timeout: 120 + + - name: "Plan Linux MAUI environment for Android" + prompt: | + I'm on a headless Linux CI server and need to build my MAUI app for Android. + I have the .NET SDK installed but nothing else. + Give me a specific plan to set up the environment, including how to find + the correct versions for everything. + assertions: + - type: "output_contains" + value: "maui-android" + - type: "output_contains" + value: "Microsoft" + - type: "output_contains" + value: "--version" + - type: "output_matches" + pattern: "sdkmanager|android command-line tools" + - type: "output_matches" + pattern: "(?i)releases-index|WorkloadDependencies|NuGet" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Recommends 'maui-android' workload, not the 'maui' meta-workload which fails on Linux" + - "Does not suggest iOS or Mac Catalyst workloads for Linux" + - "Specifies Microsoft OpenJDK as the only supported Java distribution" + - "Discovers versions dynamically from NuGet APIs rather than hardcoding them" + timeout: 120 + + - name: "Guardrail against workload update and repair" + prompt: | + My .NET MAUI project stopped building after a .NET SDK update. I think my + workloads are out of date. Should I run `dotnet workload update` or + `dotnet workload repair` to fix this? + assertions: - type: "output_contains" - value: "releases-index.json" + value: "--version" + - type: "output_matches" + pattern: "workload install" + rubric: + - "Explicitly warns against using dotnet workload update and dotnet workload repair" + - "Recommends reinstalling workloads with dotnet workload install and an explicit --version flag" + - "Explains that workload update/repair can cause version inconsistencies" + - "Describes how to discover the correct workload version from NuGet APIs" + timeout: 120 + + - name: "Diagnose non-Microsoft JDK causing build failure" + prompt: | + I'm on macOS and my .NET MAUI Android build fails with a Java-related error. + I have Adoptium Temurin JDK 17.0.12 installed and JAVA_HOME points to it. + `java -version` shows `OpenJDK Runtime Environment Temurin-17.0.12+7`. + What's wrong and how do I fix it? + assertions: + - type: "output_contains" + value: "Microsoft" + - type: "output_not_matches" + pattern: "(?i)Temurin.{0,20}(fine|correct|ok|good|supported)" + - type: "output_matches" + pattern: "JAVA_HOME" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Identifies that the JDK vendor is the problem, not the version number" + - "Recommends installing Microsoft Build of OpenJDK specifically" + - "Advises unsetting JAVA_HOME or redirecting it to the Microsoft JDK path" + - "Does not suggest Adoptium, Oracle, or other non-Microsoft JDKs as acceptable" + timeout: 120 + + - name: "Plan complete MAUI setup on Windows" + prompt: | + I'm setting up .NET MAUI development on Windows 11 from scratch. I need + to target both Android and Windows. I can't run commands right now — give + me a complete step-by-step plan with all the PowerShell commands I'll need, + including how to discover the right versions dynamically. + assertions: - type: "output_matches" - pattern: "maui-android" + pattern: "sdkmanager\\.bat" + - type: "output_matches" + pattern: "(?i)Invoke-RestMethod|Invoke-WebRequest" - type: "output_contains" - value: "Microsoft Build of OpenJDK" + value: "--version" - type: "output_contains" - value: "dotnet workload" + value: "Microsoft" + - type: "output_matches" + pattern: "(?i)releases-index|WorkloadDependencies|NuGet" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Uses sdkmanager.bat (not sdkmanager) for Android SDK management on Windows" + - "Uses PowerShell commands for API queries, not curl/jq" + - "Includes Windows SDK detection or installation" + - "Discovers all versions dynamically — does not hardcode SDK, workload, JDK, or Android versions" + - "Recommends the 'maui' workload (not 'maui-android') for Windows" + timeout: 120 + + - name: "Correct JAVA_HOME misconception" + prompt: | + I'm getting 'JAVA_HOME is not set' warnings when building my .NET MAUI + Android app on macOS. I don't have JAVA_HOME configured anywhere. Do I + need to set it? What should I set it to? + assertions: + - type: "output_matches" + pattern: "(?i)not required|not necessary|optional|auto.?detect|don't need to set" + - type: "output_contains" + value: "Microsoft" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Explains that JAVA_HOME is not required because .NET MAUI auto-detects JDK installations" + - "Clarifies that JAVA_HOME is only problematic when set to a non-Microsoft JDK" + - "Recommends verifying that Microsoft OpenJDK is installed via java -version output" + - "Does not unnecessarily instruct the user to set JAVA_HOME" + timeout: 120 + + - name: "Resist hardcoding JDK and Android SDK versions" + prompt: | + What exact JDK version and Android SDK API level do I need for .NET MAUI + right now? Just give me the version numbers so I can install them quickly. + assertions: + - type: "output_matches" + pattern: "(?i)WorkloadDependencies|NuGet|discover|dynamic" + - type: "output_matches" + pattern: "(?i)releases-index|api\\.nuget\\.org|nuget" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Does not present hardcoded version numbers as the definitive current answer" + - "Explains that requirements are discovered dynamically from WorkloadDependencies.json" + - "Describes or outlines the NuGet API discovery process to find current requirements" + - "Notes that version information may be outdated and live API queries are authoritative" + timeout: 120 + + - name: "Diagnose Android SDK missing error" + prompt: | + My MAUI build is failing with 'error XA5300: The Android SDK directory + could not be found'. I have set ANDROID_HOME to /opt/android-sdk. + How can I verify if my Android SDK installation is valid for MAUI? + What specific packages does MAUI require? + assertions: + - type: "output_matches" + pattern: "(?i)WorkloadDependencies|NuGet|manifest" + - type: "output_matches" + pattern: "build-tools" + - type: "output_matches" + pattern: "platforms" + - type: "output_matches" + pattern: "sdkmanager" + - type: "output_not_matches" + pattern: "workload update|workload repair" + rubric: + - "Identifies WorkloadDependencies.json or NuGet manifests as the source of truth for required Android SDK packages" + - "Suggests checking for specific packages such as platforms, build-tools, and platform-tools" + - "Advises using sdkmanager to list and install missing components" + - "Checks whether the path in ANDROID_HOME is valid and contains expected directories" + timeout: 120 + + - name: "Decline runtime bug debugging" + prompt: | + My .NET MAUI app builds and deploys fine on macOS, but it crashes with a + NullReferenceException right after startup. I heard about a '.NET MAUI + doctor' tool — can you use that to find the bug in my code and tell me + what line is null? + assertions: + - type: "output_matches" + pattern: "(?i)environment|setup|toolchain" + - type: "output_not_matches" + pattern: "(?i)the line.{0,20}(is|causing|null)|found the bug" + rubric: + - "Recognizes that a NullReferenceException in user code is outside the scope of the MAUI doctor environment skill" + - "Clarifies what the MAUI doctor can help with (SDKs, workloads, JDK, Android/iOS tooling) versus runtime app bugs" + - "Suggests appropriate debugging approaches (debugger, logs, stack traces) without conflating them with environment diagnosis" + - "Does not fabricate details about the user's code or pretend to locate the buggy line" + timeout: 120 + + - name: "Fix stale MAUI workloads after SDK update" + prompt: | + I updated to a newer .NET SDK on Windows 10 and now my .NET MAUI app + fails to build with workload and Android SDK errors. A colleague told me + to run 'dotnet workload update' but I'm not sure that's safe. Please lay + out a diagnostic and fix plan that brings my workloads and Android SDK + into a consistent state for the new SDK. + assertions: + - type: "output_contains" + value: "dotnet --info" + - type: "output_matches" + pattern: "dotnet workload (list|install)" + - type: "output_matches" + pattern: "install.*--version" + - type: "output_matches" + pattern: "(?i)manifest|NuGet|WorkloadDependencies" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - - "Calls out Linux is Android-only and recommends maui-android (not maui)" - - "Uses releases-index.json and NuGet APIs to discover requirements (no hardcoded versions)" - - "Avoids recommending dotnet workload update/repair" + - "Explains why dotnet workload update and repair are discouraged for MAUI and recommends explicit workload install with a matching --version" + - "Uses workload manifest and NuGet dependency data to determine which workloads and versions should be installed for the new SDK" + - "Includes checks for Android SDK packages and build tools consistent with the manifest" + - "Provides a step-by-step approach: diagnose current state, discover correct versions, reinstall, re-validate" + - "Emphasizes re-running validation after fixes to confirm a healthy environment" timeout: 120 From c141c40a855b38da5d017b901de3d77914136da8 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 4 Mar 2026 17:18:30 +0100 Subject: [PATCH 05/18] Refine eval scenarios: remove weak scenarios, fix overfitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove 'Resist hardcoding' (penalizes skill — baseline gives more useful direct answer) and 'Decline runtime bug' (skill makes agent refuse to help). Rework Android SDK scenario to test CI-oriented package discovery where baseline lacks knowledge. Replace vocabulary-level NuGet/API assertions with outcome-focused rubric items across all scenarios. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 79 +++++-------------- 1 file changed, 18 insertions(+), 61 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index 39ee3b5ea6..6a1865bd3c 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -16,15 +16,13 @@ scenarios: value: "Microsoft" - type: "output_contains" value: "--version" - - type: "output_matches" - pattern: "(?i)releases-index|WorkloadDependencies|NuGet" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - "Warns against installing Xcode from the Mac App Store and recommends Apple Developer Downloads" - "Recommends the 'maui' workload (not 'maui-android') since this is macOS" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Discovers versions dynamically via NuGet APIs rather than hardcoding them" + - "Describes how to look up current version requirements rather than hardcoding them" - "Uses --version flag when installing workloads" timeout: 120 @@ -43,15 +41,13 @@ scenarios: value: "--version" - type: "output_matches" pattern: "sdkmanager|android command-line tools" - - type: "output_matches" - pattern: "(?i)releases-index|WorkloadDependencies|NuGet" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - "Recommends 'maui-android' workload, not the 'maui' meta-workload which fails on Linux" - "Does not suggest iOS or Mac Catalyst workloads for Linux" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Discovers versions dynamically from NuGet APIs rather than hardcoding them" + - "Describes how to look up current version requirements rather than hardcoding them" timeout: 120 - name: "Guardrail against workload update and repair" @@ -108,15 +104,13 @@ scenarios: value: "--version" - type: "output_contains" value: "Microsoft" - - type: "output_matches" - pattern: "(?i)releases-index|WorkloadDependencies|NuGet" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - "Uses sdkmanager.bat (not sdkmanager) for Android SDK management on Windows" - "Uses PowerShell commands for API queries, not curl/jq" - "Includes Windows SDK detection or installation" - - "Discovers all versions dynamically — does not hardcode SDK, workload, JDK, or Android versions" + - "Does not hardcode specific SDK, workload, JDK, or Android version numbers as current" - "Recommends the 'maui' workload (not 'maui-android') for Windows" timeout: 120 @@ -139,64 +133,29 @@ scenarios: - "Does not unnecessarily instruct the user to set JAVA_HOME" timeout: 120 - - name: "Resist hardcoding JDK and Android SDK versions" - prompt: | - What exact JDK version and Android SDK API level do I need for .NET MAUI - right now? Just give me the version numbers so I can install them quickly. - assertions: - - type: "output_matches" - pattern: "(?i)WorkloadDependencies|NuGet|discover|dynamic" - - type: "output_matches" - pattern: "(?i)releases-index|api\\.nuget\\.org|nuget" - - type: "output_not_matches" - pattern: "workload update|workload repair" - rubric: - - "Does not present hardcoded version numbers as the definitive current answer" - - "Explains that requirements are discovered dynamically from WorkloadDependencies.json" - - "Describes or outlines the NuGet API discovery process to find current requirements" - - "Notes that version information may be outdated and live API queries are authoritative" - timeout: 120 - - - name: "Diagnose Android SDK missing error" + - name: "Determine required Android SDK packages for specific .NET version" prompt: | - My MAUI build is failing with 'error XA5300: The Android SDK directory - could not be found'. I have set ANDROID_HOME to /opt/android-sdk. - How can I verify if my Android SDK installation is valid for MAUI? - What specific packages does MAUI require? + I'm setting up a CI pipeline for a .NET MAUI Android app. I need to know + exactly which Android SDK packages (build-tools version, API level, + command-line tools version) are required for the MAUI workload that ships + with my current .NET SDK. I don't want to guess or use outdated docs — + how can I programmatically determine the exact package list my SDK needs? assertions: - - type: "output_matches" - pattern: "(?i)WorkloadDependencies|NuGet|manifest" - type: "output_matches" pattern: "build-tools" - type: "output_matches" - pattern: "platforms" + pattern: "(?i)api.?level|platforms;android" + - type: "output_matches" + pattern: "(?i)manifest|workload.?dependenc" - type: "output_matches" pattern: "sdkmanager" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - - "Identifies WorkloadDependencies.json or NuGet manifests as the source of truth for required Android SDK packages" - - "Suggests checking for specific packages such as platforms, build-tools, and platform-tools" - - "Advises using sdkmanager to list and install missing components" - - "Checks whether the path in ANDROID_HOME is valid and contains expected directories" - timeout: 120 - - - name: "Decline runtime bug debugging" - prompt: | - My .NET MAUI app builds and deploys fine on macOS, but it crashes with a - NullReferenceException right after startup. I heard about a '.NET MAUI - doctor' tool — can you use that to find the bug in my code and tell me - what line is null? - assertions: - - type: "output_matches" - pattern: "(?i)environment|setup|toolchain" - - type: "output_not_matches" - pattern: "(?i)the line.{0,20}(is|causing|null)|found the bug" - rubric: - - "Recognizes that a NullReferenceException in user code is outside the scope of the MAUI doctor environment skill" - - "Clarifies what the MAUI doctor can help with (SDKs, workloads, JDK, Android/iOS tooling) versus runtime app bugs" - - "Suggests appropriate debugging approaches (debugger, logs, stack traces) without conflating them with environment diagnosis" - - "Does not fabricate details about the user's code or pretend to locate the buggy line" + - "Describes a process to extract required Android SDK packages from workload manifest data rather than guessing" + - "Identifies specific package types needed: build-tools, platforms, platform-tools, and command-line tools" + - "Explains the relationship between .NET SDK version, workload manifest version, and Android SDK requirements" + - "Provides a reproducible approach suitable for CI automation" timeout: 120 - name: "Fix stale MAUI workloads after SDK update" @@ -213,14 +172,12 @@ scenarios: pattern: "dotnet workload (list|install)" - type: "output_matches" pattern: "install.*--version" - - type: "output_matches" - pattern: "(?i)manifest|NuGet|WorkloadDependencies" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - "Explains why dotnet workload update and repair are discouraged for MAUI and recommends explicit workload install with a matching --version" - - "Uses workload manifest and NuGet dependency data to determine which workloads and versions should be installed for the new SDK" - - "Includes checks for Android SDK packages and build tools consistent with the manifest" + - "Describes how to determine which workloads and versions should be installed for the new SDK" + - "Includes checks for Android SDK packages and build tools consistent with the current workload" - "Provides a step-by-step approach: diagnose current state, discover correct versions, reinstall, re-validate" - "Emphasizes re-running validation after fixes to confirm a healthy environment" timeout: 120 From 1f2862ec9622eb705c5784e768f219d31628af62 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 4 Mar 2026 17:25:38 +0100 Subject: [PATCH 06/18] Remove hardcoded JDK version workarounds in favor of dynamic discovery Replace temporary JDK 21 workaround notes with guidance to use the version from WorkloadDependencies.json. Replace hardcoded JDK paths in troubleshooting.md with {VERSION} placeholders. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/dotnet-maui-doctor/SKILL.md | 2 +- .../references/installation-commands.md | 2 +- .../references/microsoft-openjdk.md | 2 +- .../references/troubleshooting.md | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index c68d2002ed..6dce5274dc 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -100,7 +100,7 @@ Query NuGet for workload manifest → extract `WorkloadDependencies.json` → ge **Only Microsoft OpenJDK supported.** Verify `java -version` output contains "Microsoft". See `references/microsoft-openjdk.md` for detection paths and JAVA_HOME guidance. -> **⚠️ TEMPORARY WORKAROUND**: Recommend JDK 21 regardless of `jdk.recommendedVersion` until WorkloadDependencies.json is updated. Rule: If WorkloadDependencies suggests ≤21, recommend 21. If >21, use that value. +> Use the JDK version recommended by WorkloadDependencies.json (`jdk.recommendedVersion`), ensuring it satisfies the `jdk.version` range. Do not hardcode JDK versions. ### Task 6: Validate Android SDK diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md index 91ec6665d5..f754a54d3f 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md @@ -75,7 +75,7 @@ dotnet workload list **CRITICAL: Only Microsoft Build of OpenJDK is supported.** Other JDK vendors (Oracle, Azul, Amazon Corretto, Temurin, etc.) are NOT supported for .NET MAUI development. -> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated in a future Android workload release. +> Use the JDK version recommended by WorkloadDependencies.json (`jdk.recommendedVersion`), ensuring it satisfies the `jdk.version` range. Do not hardcode JDK versions. See `microsoft-openjdk.md` for detection paths, identification, and JAVA_HOME guidance. diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md index 9d17c46867..1c94e0fbe6 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md @@ -2,7 +2,7 @@ .NET MAUI requires **Microsoft Build of OpenJDK** for Android development. Other JDK distributions (Oracle, Azul, Amazon Corretto, etc.) are **not supported**. -> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated in a future Android workload release. If WorkloadDependencies suggests ≤21, use 21. If it suggests >21, use that value. +> Use the JDK version recommended by WorkloadDependencies.json (`jdk.recommendedVersion`), ensuring it satisfies the `jdk.version` range. Do not hardcode JDK versions. ## Why Microsoft OpenJDK Only? diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md index 90c5ec74e7..4a7ae81422 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md @@ -83,13 +83,13 @@ See `microsoft-openjdk.md` for complete installation paths by platform. unset JAVA_HOME # Option 2: Point to Microsoft JDK (macOS) -export JAVA_HOME=/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home +export JAVA_HOME=/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home # Option 2: Point to Microsoft JDK (Linux) -export JAVA_HOME=/usr/lib/jvm/msopenjdk-17 +export JAVA_HOME=/usr/lib/jvm/msopenjdk-{VERSION} # Option 2: Point to Microsoft JDK (Windows PowerShell) -$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-17.0.14+7" +$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-{VERSION}" # Or remove it: Remove-Item Env:JAVA_HOME ``` @@ -97,9 +97,9 @@ $env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-17.0.14+7" **Cause**: JDK version outside required range OR non-Microsoft JDK installed. -> **⚠️ TEMPORARY**: Recommend JDK 21 (not 17) until WorkloadDependencies.json is updated. +> Use the JDK version recommended by WorkloadDependencies.json (`jdk.recommendedVersion`), ensuring it satisfies the `jdk.version` range. Do not hardcode JDK versions. -**Solution**: Install Microsoft OpenJDK 21 using the [official installation guide](https://learn.microsoft.com/en-us/java/openjdk/install). +**Solution**: Install the recommended Microsoft OpenJDK version using the [official installation guide](https://learn.microsoft.com/en-us/java/openjdk/install). ### Non-Microsoft JDK detected @@ -108,7 +108,7 @@ $env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-17.0.14+7" **How to identify**: Run `java -version` - if output does NOT contain "Microsoft", wrong JDK is selected. **Solution**: -1. Install Microsoft OpenJDK 21 (see commands above) +1. Install the recommended Microsoft OpenJDK version (see commands above) 2. Set `JAVA_HOME` to Microsoft JDK path: - macOS: `/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home` - Windows: `C:\Program Files\Microsoft\jdk-{VERSION}\` @@ -123,7 +123,7 @@ $env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-17.0.14+7" /usr/libexec/java_home -V 2>&1 | grep -i microsoft # Linux - set Microsoft as default -sudo update-java-alternatives --set msopenjdk-21-amd64 +sudo update-java-alternatives --set msopenjdk-{VERSION}-amd64 ``` --- @@ -200,7 +200,7 @@ $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-$API_LE ```bash # Linux - check KVM kvm-ok - + # Enable KVM sudo modprobe kvm ``` From 97f7f1424cadf93834bf3f5a80cfa674e24966ac Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 4 Mar 2026 22:25:10 +0100 Subject: [PATCH 07/18] Improve eval scenarios: fix JAVA_HOME timeout, macOS tie, reduce overfitting - JAVA_HOME: rewrite prompt to request conceptual answer (prevents tool timeout) - macOS Xcode: add installation source guidance, remove equal-penalty assertion - Remove irrelevant workload update/repair assertions from 3 off-topic scenarios - Keep workload assertions in 5 scenarios where workload management is the topic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index 6a1865bd3c..dae98c86c5 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -4,14 +4,13 @@ scenarios: I have a clean macOS machine and want to start developing .NET MAUI apps for iOS and Android. I can't run commands right now, but I need a complete setup plan. Tell me exactly what I need to install, how to discover the - right versions, and how to verify everything works. + right versions, and how to verify everything works. Please provide the + official recommended installation sources. assertions: - type: "output_contains" value: "Xcode" - type: "output_matches" pattern: "(?i)apple developer|developer\\.apple\\.com" - - type: "output_not_matches" - pattern: "(?i)app\\s*store" - type: "output_contains" value: "Microsoft" - type: "output_contains" @@ -19,7 +18,7 @@ scenarios: - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - - "Warns against installing Xcode from the Mac App Store and recommends Apple Developer Downloads" + - "Recommends downloading Xcode from Apple Developer Downloads for version control rather than relying on the Mac App Store" - "Recommends the 'maui' workload (not 'maui-android') since this is macOS" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - "Describes how to look up current version requirements rather than hardcoding them" @@ -80,8 +79,6 @@ scenarios: pattern: "(?i)Temurin.{0,20}(fine|correct|ok|good|supported)" - type: "output_matches" pattern: "JAVA_HOME" - - type: "output_not_matches" - pattern: "workload update|workload repair" rubric: - "Identifies that the JDK vendor is the problem, not the version number" - "Recommends installing Microsoft Build of OpenJDK specifically" @@ -117,15 +114,18 @@ scenarios: - name: "Correct JAVA_HOME misconception" prompt: | I'm getting 'JAVA_HOME is not set' warnings when building my .NET MAUI - Android app on macOS. I don't have JAVA_HOME configured anywhere. Do I - need to set it? What should I set it to? + Android app on macOS. I don't have JAVA_HOME configured anywhere. + + Without running any commands or checking my environment, please explain: + 1. Is JAVA_HOME actually required for .NET MAUI? + 2. If I need a specific JDK, which one? + + I want a conceptual answer, not a troubleshooting session. assertions: - type: "output_matches" pattern: "(?i)not required|not necessary|optional|auto.?detect|don't need to set" - type: "output_contains" value: "Microsoft" - - type: "output_not_matches" - pattern: "workload update|workload repair" rubric: - "Explains that JAVA_HOME is not required because .NET MAUI auto-detects JDK installations" - "Clarifies that JAVA_HOME is only problematic when set to a non-Microsoft JDK" @@ -149,8 +149,6 @@ scenarios: pattern: "(?i)manifest|workload.?dependenc" - type: "output_matches" pattern: "sdkmanager" - - type: "output_not_matches" - pattern: "workload update|workload repair" rubric: - "Describes a process to extract required Android SDK packages from workload manifest data rather than guessing" - "Identifies specific package types needed: build-tools, platforms, platform-tools, and command-line tools" From 76285ae058be7891ec692a5e4a080481df8fa7e5 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 09:17:10 +0100 Subject: [PATCH 08/18] Reframe JAVA_HOME scenario as prevent-harmful-action pattern Rewrite prompt from conceptual yes/no question (which the agent answered from wrong general knowledge without activating the skill) to a scenario where the user is about to apply incorrect Stack Overflow advice. This mirrors the successful workload guardrail pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index dae98c86c5..5bb0dfe73c 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -111,26 +111,24 @@ scenarios: - "Recommends the 'maui' workload (not 'maui-android') for Windows" timeout: 120 - - name: "Correct JAVA_HOME misconception" + - name: "Prevent incorrect JAVA_HOME configuration" prompt: | - I'm getting 'JAVA_HOME is not set' warnings when building my .NET MAUI - Android app on macOS. I don't have JAVA_HOME configured anywhere. - - Without running any commands or checking my environment, please explain: - 1. Is JAVA_HOME actually required for .NET MAUI? - 2. If I need a specific JDK, which one? - - I want a conceptual answer, not a troubleshooting session. + My .NET MAUI Android build on macOS shows a 'JAVA_HOME is not set' warning. + I found a Stack Overflow answer telling me to add + `export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home` + to my shell profile. Is this the right fix? What should I actually do? assertions: - type: "output_matches" pattern: "(?i)not required|not necessary|optional|auto.?detect|don't need to set" - type: "output_contains" value: "Microsoft" + - type: "output_not_matches" + pattern: "(?i)Temurin.{0,20}(fine|correct|ok|good|right)" rubric: + - "Warns against setting JAVA_HOME to the Adoptium Temurin JDK path from the Stack Overflow answer" - "Explains that JAVA_HOME is not required because .NET MAUI auto-detects JDK installations" - - "Clarifies that JAVA_HOME is only problematic when set to a non-Microsoft JDK" - - "Recommends verifying that Microsoft OpenJDK is installed via java -version output" - - "Does not unnecessarily instruct the user to set JAVA_HOME" + - "Clarifies that setting JAVA_HOME to a non-Microsoft JDK can cause build failures" + - "Recommends Microsoft OpenJDK as the correct JDK if one needs to be explicitly configured" timeout: 120 - name: "Determine required Android SDK packages for specific .NET version" From 48f81d6051c3c1086eb4a848e4f843cc8772c6c7 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 10:06:58 +0100 Subject: [PATCH 09/18] Reduce overfitting: rephrase assertions and rubric to be outcome-focused - Replace literal '--version' assertions with broader 'version|pin' pattern - Rephrase Xcode rubric from skill-specific source to version control risk - Rephrase version discovery rubric from 'NuGet API' to outcome-focused - Rephrase workload install rubric from '--version flag' to 'pinned version' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/dotnet-maui-doctor/eval.yaml | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index 5bb0dfe73c..e9a10fbebe 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -13,16 +13,16 @@ scenarios: pattern: "(?i)apple developer|developer\\.apple\\.com" - type: "output_contains" value: "Microsoft" - - type: "output_contains" - value: "--version" + - type: "output_matches" + pattern: "(?i)version|pin" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - - "Recommends downloading Xcode from Apple Developer Downloads for version control rather than relying on the Mac App Store" + - "Warns about the risk of uncontrolled Xcode version updates and recommends a specific download source" - "Recommends the 'maui' workload (not 'maui-android') since this is macOS" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Describes how to look up current version requirements rather than hardcoding them" - - "Uses --version flag when installing workloads" + - "Provides a way to determine current version requirements rather than relying on potentially outdated information" + - "Pins workloads to a specific version to ensure reproducible environment setup" timeout: 120 - name: "Plan Linux MAUI environment for Android" @@ -36,8 +36,8 @@ scenarios: value: "maui-android" - type: "output_contains" value: "Microsoft" - - type: "output_contains" - value: "--version" + - type: "output_matches" + pattern: "(?i)version|pin" - type: "output_matches" pattern: "sdkmanager|android command-line tools" - type: "output_not_matches" @@ -46,7 +46,7 @@ scenarios: - "Recommends 'maui-android' workload, not the 'maui' meta-workload which fails on Linux" - "Does not suggest iOS or Mac Catalyst workloads for Linux" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Describes how to look up current version requirements rather than hardcoding them" + - "Provides a way to determine current version requirements rather than relying on potentially outdated information" timeout: 120 - name: "Guardrail against workload update and repair" @@ -55,15 +55,13 @@ scenarios: workloads are out of date. Should I run `dotnet workload update` or `dotnet workload repair` to fix this? assertions: - - type: "output_contains" - value: "--version" - type: "output_matches" - pattern: "workload install" + pattern: "(?i)version|pin" rubric: - "Explicitly warns against using dotnet workload update and dotnet workload repair" - - "Recommends reinstalling workloads with dotnet workload install and an explicit --version flag" + - "Recommends reinstalling workloads pinned to a specific version to ensure consistency" - "Explains that workload update/repair can cause version inconsistencies" - - "Describes how to discover the correct workload version from NuGet APIs" + - "Provides a method to determine the correct workload version for the current SDK" timeout: 120 - name: "Diagnose non-Microsoft JDK causing build failure" @@ -97,8 +95,8 @@ scenarios: pattern: "sdkmanager\\.bat" - type: "output_matches" pattern: "(?i)Invoke-RestMethod|Invoke-WebRequest" - - type: "output_contains" - value: "--version" + - type: "output_matches" + pattern: "(?i)version|pin" - type: "output_contains" value: "Microsoft" - type: "output_not_matches" @@ -167,12 +165,12 @@ scenarios: - type: "output_matches" pattern: "dotnet workload (list|install)" - type: "output_matches" - pattern: "install.*--version" + pattern: "(?i)version|pin" - type: "output_not_matches" pattern: "workload update|workload repair" rubric: - - "Explains why dotnet workload update and repair are discouraged for MAUI and recommends explicit workload install with a matching --version" - - "Describes how to determine which workloads and versions should be installed for the new SDK" + - "Explains why dotnet workload update and repair are discouraged for MAUI and recommends reinstalling workloads pinned to a specific version" + - "Provides a method to determine which workloads and versions should be installed for the new SDK" - "Includes checks for Android SDK packages and build tools consistent with the current workload" - "Provides a step-by-step approach: diagnose current state, discover correct versions, reinstall, re-validate" - "Emphasizes re-running validation after fixes to confirm a healthy environment" From 31b658549f1636b256c27cd9828251940dac8c5b Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 13:40:06 +0100 Subject: [PATCH 10/18] Inline critical JAVA_HOME auto-detection guidance into SKILL.md The JAVA_HOME eval scenario scored poorly because the agent couldn't read the reference file (references/microsoft-openjdk.md) and fell back on general knowledge, which incorrectly says JAVA_HOME must be set. Changes: - Task 5: Add inline JAVA_HOME guidance with decision table showing that JAVA_HOME is NOT required and MAUI auto-detects JDK installations - Common Pitfalls: Add 'Unnecessary JAVA_HOME' entry with unset commands This ensures the agent knows JAVA_HOME is unnecessary even when reference files can't be loaded. File stays at 210 lines (limit: 500). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui/skills/dotnet-maui-doctor/SKILL.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index 6dce5274dc..ce6c80df3e 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -98,10 +98,18 @@ Query NuGet for workload manifest → extract `WorkloadDependencies.json` → ge ### Task 5: Validate Java JDK -**Only Microsoft OpenJDK supported.** Verify `java -version` output contains "Microsoft". See `references/microsoft-openjdk.md` for detection paths and JAVA_HOME guidance. +**Only Microsoft OpenJDK supported.** Verify `java -version` output contains "Microsoft". See `references/microsoft-openjdk.md` for detection paths. > Use the JDK version recommended by WorkloadDependencies.json (`jdk.recommendedVersion`), ensuring it satisfies the `jdk.version` range. Do not hardcode JDK versions. +**JAVA_HOME is NOT required.** .NET MAUI tools auto-detect Microsoft OpenJDK installations from known paths. Do not tell users to set JAVA_HOME — it is unnecessary and risks pointing to a non-Microsoft JDK. + +| JAVA_HOME state | OK? | Action | +|-----------------|-----|--------| +| Not set | ✅ | None needed — auto-detection works | +| Set to Microsoft JDK | ✅ | None needed | +| Set to non-Microsoft JDK | ❌ | **Unset it** or redirect to Microsoft JDK path | + ### Task 6: Validate Android SDK Check packages from `androidsdk.packages`, `buildToolsVersion`, `apiLevel` (Task 4). See `references/installation-commands.md` for sdkmanager commands. @@ -179,6 +187,7 @@ Only run the target frameworks relevant to the user's platform and intent. This - **`maui` vs `maui-android` workload**: On Linux, the `maui` meta-workload is not available — use `maui-android` instead. On macOS/Windows, `maui` installs all platform workloads. - **`workload update` / `workload repair`**: Never use these commands. Always install workloads with an explicit `--version` flag to ensure version consistency. - **Non-Microsoft JDK**: Only Microsoft OpenJDK is supported. Other distributions (Oracle, Adoptium, Azul) will cause build failures even if the version is correct. +- **Unnecessary JAVA_HOME**: Do not set JAVA_HOME. MAUI auto-detects JDK from known install paths. Setting JAVA_HOME to a non-Microsoft JDK (e.g., Temurin) overrides auto-detection and causes failures. If already set to a wrong JDK, **unset it** (`unset JAVA_HOME` / `Remove-Item Env:JAVA_HOME`). - **Hardcoded versions**: Never hardcode SDK, workload, or dependency versions. Always discover them dynamically from the NuGet APIs (see Task 4). - **Android SDK `sdkmanager` on Windows**: Use `sdkmanager.bat`, not `sdkmanager`, on Windows. - **Stale training data**: LLM training data may reference outdated .NET versions. Always check the releases-index.json to discover the current active release. From fa03153101d612a7ffb12138bd564ab53a1e26bd Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 13:48:33 +0100 Subject: [PATCH 11/18] Inline JAVA_HOME auto-detection knowledge into SKILL.md Add JAVA_HOME guidance directly to Task 5, Task 9, and Common Pitfalls so the agent knows JAVA_HOME is not required even when reference files can't be read. Based on Redth's original microsoft-openjdk.md reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index ce6c80df3e..6eb2943dac 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -136,7 +136,7 @@ See `references/installation-commands.md` for all commands. Key rules: - **Workloads**: Always use `--version` flag. Never use `workload update` or `workload repair`. -- **JDK**: Only install Microsoft OpenJDK. +- **JDK**: Only install Microsoft OpenJDK. Do not set JAVA_HOME (auto-detected). - **Android SDK**: Use `sdkmanager` (from Android SDK command-line tools). On Windows use `sdkmanager.bat`. ### Task 10: Re-validate From fe40be8e46eb876e4396b734f095adbcf3e3da42 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 16:30:09 +0100 Subject: [PATCH 12/18] Address code review feedback from Copilot - Fix cmd.exe syntax in installation-commands.md (use PowerShell $env:) - Replace hardcoded simulator device/runtime with placeholders - Add System.IO.Compression.FileSystem assembly load for PS 5.1 compat - Clarify workload reinstall example is macOS-specific (omit ios on Linux) - Replace hardcoded android-35 with $API_LEVEL placeholder Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../references/installation-commands-macos.md | 5 +++-- .../dotnet-maui-doctor/references/installation-commands.md | 4 ++-- .../skills/dotnet-maui-doctor/references/troubleshooting.md | 5 +++-- .../references/workload-dependencies-discovery.md | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md index 34131f5b5c..296cd22c1c 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md @@ -55,6 +55,7 @@ xcrun simctl list devices available xcrun simctl list devicetypes | grep iPhone xcrun simctl list runtimes | grep iOS -# Create one using the newest iPhone type and latest iOS runtime -xcrun simctl create "iPhone 16 Pro" "com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro" "com.apple.CoreSimulator.SimRuntime.iOS-18-0" +# Create one using a chosen device type and runtime from the lists above +# Replace and with identifiers from the commands above +xcrun simctl create "My iPhone Simulator" "" "" ``` diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md index f754a54d3f..5f0a179f68 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md @@ -107,8 +107,8 @@ echo $ANDROID_SDK_ROOT # macOS/Linux $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --version -# Windows -%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin\sdkmanager.bat --version +# Windows (PowerShell) +& "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --version ``` ### Installing Android SDK Command-Line Tools diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md index 4a7ae81422..5c0df11f24 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md @@ -41,7 +41,7 @@ dotnet workload install maui --version $WORKLOAD_VERSION # First, find the correct workload set version for your SDK # Query NuGet APIs (see workload-dependencies-discovery.md) -# Then reinstall with explicit version +# Then reinstall with explicit version (macOS example — omit ios/maccatalyst on Linux) dotnet workload install maui android ios maccatalyst --version $WORKLOAD_VERSION ``` @@ -229,7 +229,8 @@ dotnet workload install android --version $WORKLOAD_VERSION **Solution**: ```bash -$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-35" +# Discover required API level from WorkloadDependencies.json, then: +$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "platforms;android-$API_LEVEL" ``` ### "MSB4019: The imported project was not found" diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md index e781c3bc85..6ba50ce155 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md @@ -129,6 +129,7 @@ unzip -p manifest.nupkg data/WorkloadDependencies.json **PowerShell:** ```powershell Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/{packageid}/{version}/{packageid}.{version}.nupkg" -OutFile manifest.nupkg +Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::OpenRead("manifest.nupkg") $entry = $zip.Entries | Where-Object { $_.FullName -eq "data/WorkloadDependencies.json" } $reader = [System.IO.StreamReader]::new($entry.Open()) From 9a6f33f1ac6f413d095202a439d34c02a93ae4b8 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 5 Mar 2026 21:55:41 +0100 Subject: [PATCH 13/18] Address jonathanpeppers review feedback - Add Apple Developer login/2FA note for Xcode downloads - Fix Windows SDK detection: extract KitsRoot10 and version subkeys instead of dumping full registry (was outputting noise) - Replace manual NuGet API approach with dotnet workload search version CLI command for discovering workload versions - Reframe JAVA_HOME guidance: report as anomaly rather than prescribing unset/set commands (per jonathanpeppers recommendation) - Use $env:ProgramFiles instead of hardcoded C:\Program Files paths in PowerShell commands - Update SKILL.md to match: softer JAVA_HOME guidance, improved Windows SDK detection command Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/dotnet-maui-doctor/SKILL.md | 6 ++--- .../references/installation-commands-macos.md | 2 ++ .../installation-commands-windows.md | 7 +++++- .../references/installation-commands.md | 16 ++++--------- .../references/microsoft-openjdk.md | 4 +++- .../references/troubleshooting-windows.md | 6 +++-- .../references/troubleshooting.md | 23 +++++-------------- 7 files changed, 28 insertions(+), 36 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index 6eb2943dac..98f054f6b7 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -108,7 +108,7 @@ Query NuGet for workload manifest → extract `WorkloadDependencies.json` → ge |-----------------|-----|--------| | Not set | ✅ | None needed — auto-detection works | | Set to Microsoft JDK | ✅ | None needed | -| Set to non-Microsoft JDK | ❌ | **Unset it** or redirect to Microsoft JDK path | +| Set to non-Microsoft JDK | ⚠️ | **Report as anomaly** — let user decide to unset or redirect | ### Task 6: Validate Android SDK @@ -125,7 +125,7 @@ Compare against `xcode.version` range from Task 4. See `references/installation- ### Task 8: Validate Windows SDK (Windows Only) ```powershell -Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" +(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 ``` See `references/installation-commands-windows.md`. @@ -187,7 +187,7 @@ Only run the target frameworks relevant to the user's platform and intent. This - **`maui` vs `maui-android` workload**: On Linux, the `maui` meta-workload is not available — use `maui-android` instead. On macOS/Windows, `maui` installs all platform workloads. - **`workload update` / `workload repair`**: Never use these commands. Always install workloads with an explicit `--version` flag to ensure version consistency. - **Non-Microsoft JDK**: Only Microsoft OpenJDK is supported. Other distributions (Oracle, Adoptium, Azul) will cause build failures even if the version is correct. -- **Unnecessary JAVA_HOME**: Do not set JAVA_HOME. MAUI auto-detects JDK from known install paths. Setting JAVA_HOME to a non-Microsoft JDK (e.g., Temurin) overrides auto-detection and causes failures. If already set to a wrong JDK, **unset it** (`unset JAVA_HOME` / `Remove-Item Env:JAVA_HOME`). +- **Unnecessary JAVA_HOME**: Do not set JAVA_HOME. MAUI auto-detects JDK from known install paths. If JAVA_HOME is set to a non-Microsoft JDK (e.g., Temurin), report this as an anomaly — it may override auto-detection and cause failures. Let the user decide whether to unset it. - **Hardcoded versions**: Never hardcode SDK, workload, or dependency versions. Always discover them dynamically from the NuGet APIs (see Task 4). - **Android SDK `sdkmanager` on Windows**: Use `sdkmanager.bat`, not `sdkmanager`, on Windows. - **Stale training data**: LLM training data may reference outdated .NET versions. Always check the releases-index.json to discover the current active release. diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md index 296cd22c1c..149f593da6 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md @@ -8,6 +8,8 @@ Download a specific version from [Apple Developer Downloads](https://developer.apple.com/download/all/), matching the `xcode.version` range from WorkloadDependencies.json. +> **Note**: Downloading from Apple Developer Downloads requires signing in with an Apple ID (with two-factor authentication). The agent cannot automate this — tell the user to download Xcode manually and then continue with the remaining steps. + ### Install Command Line Tools ```bash diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md index 553adcc18f..6650b14f65 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md @@ -7,7 +7,12 @@ The Windows SDK is required for WinUI 3 / Windows targets. ### Detect Windows SDK ```powershell -Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue +# Get the Windows 10/11 SDK root path +$kitsRoot = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 + +# List installed SDK versions +Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue | + ForEach-Object { $_.PSChildName } ``` ### Install Windows SDK diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md index 5f0a179f68..fe9716a472 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md @@ -25,19 +25,11 @@ For scripted/CI installs, use the [dotnet-install scripts](https://learn.microso **Always use explicit workload set version** to ensure consistent, reproducible installs. -First, find the latest workload set version using the process in `workload-dependencies-discovery.md`: +First, find the latest workload set version: ```bash -# Discover NuGet search endpoint from service index -NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ - jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) - -# Query for latest workload set -# SDK band = first 2 segments of SDK version (e.g., 10.0 from 10.0.102) -curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.$SDK_BAND&prerelease=false" | \ - jq '.data[] | select(.id | test("^Microsoft.NET.Workloads.$SDK_BAND.[0-9]+$")) | {id, version}' - -# Convert NuGet version to CLI version: -# NuGet A.B.C → CLI A.0.B (e.g., NuGet 10.102.0 → CLI 10.0.102) +# Use the CLI to discover available workload versions for your SDK +dotnet workload search version $SDK_VERSION +# e.g., dotnet workload search version 10.0.103 ``` Then install with explicit version: diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md index 1c94e0fbe6..dc5a103f02 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md @@ -49,7 +49,7 @@ Registry: `HKLM\SOFTWARE\Microsoft\JDK\{VERSION}` Detection: ```powershell -Get-ChildItem "C:\Program Files\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue +Get-ChildItem "$env:ProgramFiles\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue java -version 2>&1 | Select-String "Microsoft" ``` @@ -95,6 +95,8 @@ unset JAVA_HOME Remove-Item Env:JAVA_HOME ``` +> **Note**: Rather than automatically unsetting JAVA_HOME, report it as an anomaly to the user and let them decide. Example: "JAVA_HOME is set to a non-Microsoft JDK (Oracle). .NET MAUI auto-detects Microsoft OpenJDK, so JAVA_HOME is not needed. This may cause build issues." + ### Multiple JDKs Installed 1. Run `java -version` and check for "Microsoft" in output diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md index 5d75500a95..0bea242858 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md @@ -16,10 +16,12 @@ ```powershell # Windows SDK detection -Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue +$kitsRoot = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 +Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue | + ForEach-Object { $_.PSChildName } # JDK detection (Windows-specific) -Get-ChildItem "C:\Program Files\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue +Get-ChildItem "$env:ProgramFiles\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue java -version 2>&1 | Select-String "Microsoft" # Android SDK location diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md index 5c0df11f24..5d520ed2b7 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md @@ -78,20 +78,12 @@ See `microsoft-openjdk.md` for complete installation paths by platform. - ✅ `JAVA_HOME` points to Microsoft JDK → Fine **Solution (only if JAVA_HOME is set to wrong JDK):** -```bash -# Option 1: Unset JAVA_HOME (let tools auto-detect) -unset JAVA_HOME - -# Option 2: Point to Microsoft JDK (macOS) -export JAVA_HOME=/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home -# Option 2: Point to Microsoft JDK (Linux) -export JAVA_HOME=/usr/lib/jvm/msopenjdk-{VERSION} +Report this as an anomaly to the user: "JAVA_HOME is set to a non-Microsoft JDK. .NET MAUI auto-detects Microsoft OpenJDK, so JAVA_HOME is not needed and may cause build issues." -# Option 2: Point to Microsoft JDK (Windows PowerShell) -$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-{VERSION}" -# Or remove it: Remove-Item Env:JAVA_HOME -``` +The user can then decide to: +- Unset JAVA_HOME (recommended — lets auto-detection work) +- Point it to Microsoft JDK if they have a specific reason to keep it set ### "Unsupported Java version" or "Wrong JDK vendor" @@ -109,10 +101,7 @@ $env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-{VERSION}" **Solution**: 1. Install the recommended Microsoft OpenJDK version (see commands above) -2. Set `JAVA_HOME` to Microsoft JDK path: - - macOS: `/Library/Java/JavaVirtualMachines/microsoft-{VERSION}.jdk/Contents/Home` - - Windows: `C:\Program Files\Microsoft\jdk-{VERSION}\` - - Linux: `/usr/lib/jvm/msopenjdk-{VERSION}` +2. If `JAVA_HOME` is set and points to a non-Microsoft JDK, report this as an anomaly — the user should unset it or point it to the Microsoft JDK path 3. Optionally uninstall the non-Microsoft JDK ### Multiple JDKs installed, wrong one selected @@ -287,7 +276,7 @@ dotnet workload install [workload-name] --version $WORKLOAD_VERSION **Key point about JAVA_HOME:** - ✅ Not set → Fine, tools auto-detect Microsoft JDK - ✅ Set to Microsoft JDK path → Fine -- ❌ Set to non-Microsoft JDK → Problem! Unset or fix it +- ❌ Set to non-Microsoft JDK → Anomaly! Report to user **Note**: The .NET MAUI toolchain auto-detects most paths. Only set these manually if auto-detection fails or wrong JDK is being selected. From 843b84dadb369f0cf2342debba9672bb7053bbee Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Fri, 6 Mar 2026 13:05:39 +0100 Subject: [PATCH 14/18] Address Redth review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove Windows SDK detection commands — installed automatically via MAUI workload/VS Installer (per Redth recommendation) - Use dotnet workload search version --format json --take 1 for workload version discovery instead of NuGet search API (per both Redth and jonathanpeppers) - Update workload-dependencies-discovery.md Step 2 to match - Expand Android SDK detection with known filesystem paths instead of relying solely on environment variables Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/dotnet-maui-doctor/SKILL.md | 6 +- .../installation-commands-windows.md | 17 +---- .../references/installation-commands.md | 16 +++-- .../references/troubleshooting-windows.md | 8 +-- .../workload-dependencies-discovery.md | 62 ++++++------------- 5 files changed, 32 insertions(+), 77 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md index 98f054f6b7..2063b18877 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/SKILL.md @@ -124,11 +124,7 @@ Compare against `xcode.version` range from Task 4. See `references/installation- ### Task 8: Validate Windows SDK (Windows Only) -```powershell -(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 -``` - -See `references/installation-commands-windows.md`. +The Windows SDK is typically installed as part of the .NET MAUI workload or Visual Studio. See `references/installation-commands-windows.md`. ### Task 9: Remediation diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md index 6650b14f65..f51f2d75a5 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-windows.md @@ -2,21 +2,6 @@ ## Windows SDK -The Windows SDK is required for WinUI 3 / Windows targets. - -### Detect Windows SDK - -```powershell -# Get the Windows 10/11 SDK root path -$kitsRoot = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 - -# List installed SDK versions -Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue | - ForEach-Object { $_.PSChildName } -``` - -### Install Windows SDK - -The Windows SDK is typically installed as part of the .NET MAUI workload or via the Visual Studio Installer. +The Windows SDK is required for WinUI 3 / Windows targets. It is typically installed automatically as part of the .NET MAUI workload or via the Visual Studio Installer. For standalone installation, see: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md index fe9716a472..e55b42925f 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands.md @@ -27,9 +27,9 @@ For scripted/CI installs, use the [dotnet-install scripts](https://learn.microso First, find the latest workload set version: ```bash -# Use the CLI to discover available workload versions for your SDK -dotnet workload search version $SDK_VERSION -# e.g., dotnet workload search version 10.0.103 +# Use the CLI to discover the latest workload version for your SDK +dotnet workload search version --format json --take 1 +# Returns: [{"workloadVersion":"10.0.103"}] ``` Then install with explicit version: @@ -90,10 +90,14 @@ java -version echo $ANDROID_HOME echo $ANDROID_SDK_ROOT -# Common SDK locations: +# Known SDK locations by platform: # macOS: ~/Library/Android/sdk -# Linux: ~/Android/Sdk -# Windows: %LOCALAPPDATA%\Android\Sdk +# Linux: ~/Android/Sdk or /usr/lib/android-sdk +# Windows: $env:LOCALAPPDATA\Android\Sdk + +# Check known paths directly +ls -d ~/Library/Android/sdk 2>/dev/null # macOS +ls -d ~/Android/Sdk 2>/dev/null # Linux # Check if sdkmanager is available # macOS/Linux diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md index 0bea242858..cea34f3a35 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting-windows.md @@ -15,18 +15,14 @@ ## Windows Diagnostic Commands ```powershell -# Windows SDK detection -$kitsRoot = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue).KitsRoot10 -Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue | - ForEach-Object { $_.PSChildName } - # JDK detection (Windows-specific) Get-ChildItem "$env:ProgramFiles\Microsoft" -Filter "jdk-*" -ErrorAction SilentlyContinue java -version 2>&1 | Select-String "Microsoft" # Android SDK location echo $env:ANDROID_SDK_ROOT -# Default: $env:LOCALAPPDATA\Android\Sdk +# Known paths: $env:LOCALAPPDATA\Android\Sdk +ls "$env:LOCALAPPDATA\Android\Sdk" -ErrorAction SilentlyContinue # Android SDK list installed (Windows) & "$env:ANDROID_SDK_ROOT\cmdline-tools\latest\bin\sdkmanager.bat" --list_installed diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md index 6ba50ce155..fd54974725 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md @@ -42,45 +42,24 @@ Extract `latest-sdk` and derive SDK band: - `10.0.102` → band `10.0.100` (hundreds digit) - `10.0.205` → band `10.0.200` -### Step 2: Find Workload Set Package +### Step 2: Find Workload Set Version -First, discover the NuGet search endpoint from the service index: +Use the `dotnet workload search version` command to discover the latest workload set version: -**Bash:** ```bash -# Get the SearchQueryService URL from the NuGet v3 service index -NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ - jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) +dotnet workload search version --format json --take 1 +# Returns: [{"workloadVersion":"10.0.103"}] ``` -**PowerShell:** ```powershell -$serviceIndex = Invoke-RestMethod "https://api.nuget.org/v3/index.json" -$nugetSearchUrl = ($serviceIndex.resources | Where-Object { $_.'@type' -eq 'SearchQueryService' } | Select-Object -First 1).'@id' +dotnet workload search version --format json --take 1 | ConvertFrom-Json ``` -Then search for the workload set package: +The returned `workloadVersion` is the CLI version to use with `--version` flag. -**Bash:** -```bash -curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.{MAJOR}.0&prerelease=false&semVerLevel=2.0.0" -``` - -**PowerShell:** -```powershell -Invoke-RestMethod "$nugetSearchUrl`?q=Microsoft.NET.Workloads.{MAJOR}.0&prerelease=false&semVerLevel=2.0.0" -``` - -Filter results: -- Match `Microsoft.NET.Workloads.{major}.{band}` (e.g., `Microsoft.NET.Workloads.10.0.100`) -- Exclude `.Msi.*` packages -- Pick highest version - -**Version conversion**: NuGet `10.102.0` → CLI `10.0.102` -``` -parts = nugetVersion.split('.') -cliVersion = parts[0] + ".0." + parts[1] -``` +To convert this to the NuGet package version (needed for Steps 3-4): +- CLI `10.0.102` → NuGet `10.102.0` (remove middle `.0.`, combine) +- The NuGet package is: `Microsoft.NET.Workloads.{band}` where band = CLI version (e.g., `Microsoft.NET.Workloads.10.0.100`) ### Step 3: Download Workload Set Manifest @@ -195,13 +174,10 @@ curl -s "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/release jq '.["releases-index"][] | select(.["channel-version"]=="10.0") | .["latest-sdk"]' # Result: "10.0.102" → band "10.0.100" -# Step 2: Discover NuGet search endpoint and find workload set -NUGET_SEARCH_URL=$(curl -s "https://api.nuget.org/v3/index.json" | \ - jq -r '.resources[] | select(.["@type"]=="SearchQueryService") | .["@id"]' | head -1) -curl -s "$NUGET_SEARCH_URL?q=Microsoft.NET.Workloads.10.0&prerelease=false" | \ - jq '.data[] | select(.id=="Microsoft.NET.Workloads.10.0.100") | {id, version}' -# Result: { "id": "Microsoft.NET.Workloads.10.0.100", "version": "10.102.0" } -# CLI version: 10.0.102 +# Step 2: Get latest workload set version +dotnet workload search version --format json --take 1 +# Result: [{"workloadVersion":"10.0.102"}] +# NuGet version: 10.102.0 # Step 3: Download workload set manifest curl -so workloadset.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.10.0.100/10.102.0/microsoft.net.workloads.10.0.100.10.102.0.nupkg" @@ -222,12 +198,10 @@ $sdkInfo = $releases.'releases-index' | Where-Object { $_.'channel-version' -eq $latestSdk = $sdkInfo.'latest-sdk' # Result: "10.0.102" → band "10.0.100" -# Step 2: Discover NuGet search endpoint and find workload set -$serviceIndex = Invoke-RestMethod "https://api.nuget.org/v3/index.json" -$searchUrl = ($serviceIndex.resources | Where-Object { $_.'@type' -eq 'SearchQueryService' } | Select-Object -First 1).'@id' -$result = Invoke-RestMethod "$searchUrl`?q=Microsoft.NET.Workloads.10.0&prerelease=false" -$workloadSet = $result.data | Where-Object { $_.id -eq 'Microsoft.NET.Workloads.10.0.100' } -# Result: version "10.102.0", CLI version: 10.0.102 +# Step 2: Get latest workload set version +$workloadVersion = (dotnet workload search version --format json --take 1 | ConvertFrom-Json).workloadVersion +# Result: "10.0.102" +# NuGet version: 10.102.0 # Step 3: Download workload set manifest and extract Invoke-WebRequest "https://api.nuget.org/v3-flatcontainer/microsoft.net.workloads.10.0.100/10.102.0/microsoft.net.workloads.10.0.100.10.102.0.nupkg" -OutFile workloadset.nupkg @@ -261,7 +235,7 @@ $reader.Dispose(); $zip.Dispose() | NuGet service index | `https://api.nuget.org/v3/index.json` | | Download package | `https://api.nuget.org/v3-flatcontainer/{id}/{version}/{id}.{version}.nupkg` | -**Discover the search endpoint** from the service index by filtering for `SearchQueryService` type. Do not hardcode search URLs — they are regional and may change. +**Workload version discovery**: Use `dotnet workload search version --format json --take 1` instead of querying NuGet search APIs directly. The NuGet download URLs are still needed for Steps 3-4 (manifest extraction). **Important**: Package IDs must be lowercase in download URLs. From de3465d7583a0aaf8db685198abfcb298062fc79 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Fri, 6 Mar 2026 17:18:36 +0100 Subject: [PATCH 15/18] Align eval rubric with reviewer feedback to reduce overfitting Replace technique-specific rubric items with outcome-focused criteria: - Replace PowerShell API query check with dotnet CLI discovery check - Replace manifest extraction check with workload-version-based discovery - Replace prescriptive version discovery with CLI/docs verification - Convert workload update/repair regex assertions to rubric criteria - Remove Invoke-RestMethod assertion (no longer using API queries) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/dotnet-maui/dotnet-maui-doctor/eval.yaml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml index e9a10fbebe..f3148dce9e 100644 --- a/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml +++ b/tests/dotnet-maui/dotnet-maui-doctor/eval.yaml @@ -15,14 +15,13 @@ scenarios: value: "Microsoft" - type: "output_matches" pattern: "(?i)version|pin" - - type: "output_not_matches" - pattern: "workload update|workload repair" rubric: - "Warns about the risk of uncontrolled Xcode version updates and recommends a specific download source" - "Recommends the 'maui' workload (not 'maui-android') since this is macOS" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Provides a way to determine current version requirements rather than relying on potentially outdated information" + - "Verifies version requirements using CLI tools or official documentation rather than relying on hardcoded versions" - "Pins workloads to a specific version to ensure reproducible environment setup" + - "Does not recommend 'dotnet workload update' or 'dotnet workload repair' as the primary installation method" timeout: 120 - name: "Plan Linux MAUI environment for Android" @@ -40,13 +39,12 @@ scenarios: pattern: "(?i)version|pin" - type: "output_matches" pattern: "sdkmanager|android command-line tools" - - type: "output_not_matches" - pattern: "workload update|workload repair" rubric: - "Recommends 'maui-android' workload, not the 'maui' meta-workload which fails on Linux" - "Does not suggest iOS or Mac Catalyst workloads for Linux" - "Specifies Microsoft OpenJDK as the only supported Java distribution" - - "Provides a way to determine current version requirements rather than relying on potentially outdated information" + - "Verifies version requirements using CLI tools or official documentation rather than relying on hardcoded versions" + - "Does not recommend 'dotnet workload update' or 'dotnet workload repair' as the primary installation method" timeout: 120 - name: "Guardrail against workload update and repair" @@ -93,8 +91,6 @@ scenarios: assertions: - type: "output_matches" pattern: "sdkmanager\\.bat" - - type: "output_matches" - pattern: "(?i)Invoke-RestMethod|Invoke-WebRequest" - type: "output_matches" pattern: "(?i)version|pin" - type: "output_contains" @@ -103,8 +99,7 @@ scenarios: pattern: "workload update|workload repair" rubric: - "Uses sdkmanager.bat (not sdkmanager) for Android SDK management on Windows" - - "Uses PowerShell commands for API queries, not curl/jq" - - "Includes Windows SDK detection or installation" + - "Uses dotnet CLI commands (e.g. dotnet workload search) to discover workload versions rather than hardcoding or querying external APIs directly" - "Does not hardcode specific SDK, workload, JDK, or Android version numbers as current" - "Recommends the 'maui' workload (not 'maui-android') for Windows" timeout: 120 @@ -146,7 +141,7 @@ scenarios: - type: "output_matches" pattern: "sdkmanager" rubric: - - "Describes a process to extract required Android SDK packages from workload manifest data rather than guessing" + - "Determines required Android SDK packages based on the installed workload version rather than guessing" - "Identifies specific package types needed: build-tools, platforms, platform-tools, and command-line tools" - "Explains the relationship between .NET SDK version, workload manifest version, and Android SDK requirements" - "Provides a reproducible approach suitable for CI automation" From 6c5c44c805e15ad0bf9932c28f9ca681675b9e89 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Fri, 6 Mar 2026 17:52:55 +0100 Subject: [PATCH 16/18] Align JAVA_HOME guidance with reviewer consensus, add Xcode download expectations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Consistently use ⚠️ anomaly approach for non-Microsoft JAVA_HOME across microsoft-openjdk.md and troubleshooting.md (matching SKILL.md) - Remove contradictory Note in microsoft-openjdk.md that conflicted with table - Reframe unset commands as user's choice, not automatic action - Add Xcode download size (~12GB) and time expectations per Redth's feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../references/installation-commands-macos.md | 2 +- .../dotnet-maui-doctor/references/microsoft-openjdk.md | 10 +++++----- .../dotnet-maui-doctor/references/troubleshooting.md | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md index 149f593da6..abfe20c94f 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/installation-commands-macos.md @@ -8,7 +8,7 @@ Download a specific version from [Apple Developer Downloads](https://developer.apple.com/download/all/), matching the `xcode.version` range from WorkloadDependencies.json. -> **Note**: Downloading from Apple Developer Downloads requires signing in with an Apple ID (with two-factor authentication). The agent cannot automate this — tell the user to download Xcode manually and then continue with the remaining steps. +> **Note**: Downloading from Apple Developer Downloads requires signing in with an Apple ID (with two-factor authentication). Xcode is approximately 12 GB and may take 30 minutes or more to download. The agent cannot automate this — tell the user to download Xcode manually, set expectations for the download size and wait time, then continue with the remaining steps. ### Install Command Line Tools diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md index dc5a103f02..3c7dcc0bcf 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md @@ -84,9 +84,11 @@ For installation instructions, refer to the official Microsoft documentation: |-------|-----|--------| | Not set | ✅ | None needed, auto-detection works | | Set to Microsoft JDK path | ✅ | None needed | -| Set to non-Microsoft JDK | ❌ | Unset it or point to Microsoft JDK | +| Set to non-Microsoft JDK | ⚠️ | Report as anomaly — let user decide to unset or redirect | -To unset: +Report a non-Microsoft JAVA_HOME as an anomaly: "JAVA_HOME is set to a non-Microsoft JDK. .NET MAUI auto-detects Microsoft OpenJDK, so JAVA_HOME is not needed and may cause build issues." + +If the user decides to unset: ```bash # macOS/Linux unset JAVA_HOME @@ -95,12 +97,10 @@ unset JAVA_HOME Remove-Item Env:JAVA_HOME ``` -> **Note**: Rather than automatically unsetting JAVA_HOME, report it as an anomaly to the user and let them decide. Example: "JAVA_HOME is set to a non-Microsoft JDK (Oracle). .NET MAUI auto-detects Microsoft OpenJDK, so JAVA_HOME is not needed. This may cause build issues." - ### Multiple JDKs Installed 1. Run `java -version` and check for "Microsoft" in output -2. If wrong vendor and `JAVA_HOME` is set → unset it or point to Microsoft JDK path +2. If wrong vendor and `JAVA_HOME` is set → report as anomaly; user should unset or redirect to Microsoft JDK path 3. If wrong vendor and `JAVA_HOME` is NOT set → the non-Microsoft JDK may be first in PATH; install Microsoft JDK and it should take precedence 4. Restart terminal after changes diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md index 5d520ed2b7..68b66c15fe 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/troubleshooting.md @@ -73,7 +73,7 @@ See `microsoft-openjdk.md` for complete installation paths by platform. **This is usually NOT a problem.** The .NET MAUI toolchain auto-detects JDK installations without needing `JAVA_HOME`. **When JAVA_HOME matters:** -- ❌ `JAVA_HOME` is set but points to a **non-Microsoft JDK** → Fix by unsetting or pointing to Microsoft JDK +- ⚠️ `JAVA_HOME` is set but points to a **non-Microsoft JDK** → Report as anomaly; user should unset or redirect to Microsoft JDK - ✅ `JAVA_HOME` is not set → Fine, tools will auto-detect - ✅ `JAVA_HOME` points to Microsoft JDK → Fine @@ -82,7 +82,7 @@ See `microsoft-openjdk.md` for complete installation paths by platform. Report this as an anomaly to the user: "JAVA_HOME is set to a non-Microsoft JDK. .NET MAUI auto-detects Microsoft OpenJDK, so JAVA_HOME is not needed and may cause build issues." The user can then decide to: -- Unset JAVA_HOME (recommended — lets auto-detection work) +- Unset JAVA_HOME (lets auto-detection work) - Point it to Microsoft JDK if they have a specific reason to keep it set ### "Unsupported Java version" or "Wrong JDK vendor" @@ -267,7 +267,7 @@ dotnet workload install [workload-name] --version $WORKLOAD_VERSION | Variable | Purpose | Required | Notes | |----------|---------|----------|-------| -| `JAVA_HOME` | JDK location | No | Only problematic if set to non-Microsoft JDK | +| `JAVA_HOME` | JDK location | No | Report as anomaly if set to non-Microsoft JDK | | `ANDROID_HOME` | Android SDK location | No | Auto-detected | | `ANDROID_SDK_ROOT` | Android SDK location | No | Alternative to ANDROID_HOME | | `DOTNET_ROOT` | .NET SDK location | No | Usually auto-detected | @@ -276,7 +276,7 @@ dotnet workload install [workload-name] --version $WORKLOAD_VERSION **Key point about JAVA_HOME:** - ✅ Not set → Fine, tools auto-detect Microsoft JDK - ✅ Set to Microsoft JDK path → Fine -- ❌ Set to non-Microsoft JDK → Anomaly! Report to user +- ⚠️ Set to non-Microsoft JDK → Anomaly — report to user **Note**: The .NET MAUI toolchain auto-detects most paths. Only set these manually if auto-detection fails or wrong JDK is being selected. From f77a538bda854690c02ca05543f535aa5b89b1de Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Fri, 6 Mar 2026 20:34:02 +0100 Subject: [PATCH 17/18] Update plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md Co-authored-by: Jonathan Peppers --- .../references/workload-dependencies-discovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md index fd54974725..7c2bed87b6 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/workload-dependencies-discovery.md @@ -124,7 +124,7 @@ $reader.Dispose(); $zip.Dispose() "microsoft.net.sdk.android": { "jdk": { "version": "[17.0,22.0)", - "recommendedVersion": "17.0.14" + "recommendedVersion": "21.0.8" }, "androidsdk": { "packages": ["build-tools;35.0.0", "platform-tools", "platforms;android-35", "cmdline-tools;13.0"], From 38914a54a9298a6e877ee06ba835ed94c1dcfd8c Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Fri, 6 Mar 2026 20:35:18 +0100 Subject: [PATCH 18/18] Update JDK example to version 21 per jonathanpeppers feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dotnet-maui-doctor/references/microsoft-openjdk.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md index 3c7dcc0bcf..d072a45921 100644 --- a/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md +++ b/plugins/dotnet-maui/skills/dotnet-maui-doctor/references/microsoft-openjdk.md @@ -16,9 +16,9 @@ Run `java -version`. Microsoft OpenJDK output contains `Microsoft` in the runtime line: ``` -openjdk version "17.0.14" 2025-01-21 LTS -OpenJDK Runtime Environment Microsoft-XXXXXXX (build 17.0.14+7-LTS) -OpenJDK 64-Bit Server VM Microsoft-XXXXXXX (build 17.0.14+7-LTS, mixed mode, sharing) +openjdk version "21.0.6" 2025-01-21 LTS +OpenJDK Runtime Environment Microsoft-XXXXXXX (build 21.0.6+7-LTS) +OpenJDK 64-Bit Server VM Microsoft-XXXXXXX (build 21.0.6+7-LTS, mixed mode, sharing) ``` If the output does NOT contain "Microsoft", the wrong JDK is installed or selected.