| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 36 | 60 | 0% |
| Commands | 1 | 18 | 9 | 4% |
| Section tags | 6 | 4 | 2 | 50% |
What each file covers
Sections
0 shared · 36 only in A · 60 only in B- − GitHub Copilot Development Environment Instructions
- − Code Review Instructions
- − Repository Overview
- − Key Technologies
- − Development Environment Setup
- − Platform-Specific Requirements
- − Project Structure
- − Important Directories
- − Platform-Specific Code Organization
- − Platform-Specific File Extensions
- − Sample Projects
- − Development Workflow
- − Testing
- − CI Pipelines (Azure DevOps)
- − Investigating CI Failures
- − Gradle / Maven Dependency Failures (CFSClean)
- − Code Formatting
- − Contribution Guidelines
- − Handling Existing PRs for Assigned Issues
- − Auto-Generated Files (Never Commit)
- − PublicAPI.Unshipped.txt File Management
- − Branching
- − Git Workflow (Copilot CLI Rules)
- − Create a feature branch (NEVER work directly on main)
- − Make commits normally
- − Push to remote (for new branches)
- − For subsequent pushes on the same branch
- − Check out the PR branch directly (do NOT create a new branch off it)
- − Make fixes and commit to the PR branch
- − Documentation
- − Opening PRs
- − Custom Agents and Skills
- − Skills vs Agents
- − Available Custom Agents
- − Reusable Skills
- − Using Custom Agents
- + Sandbox Testing Guide
- + When This Applies
- + 🚨 CRITICAL VALIDATION RULES - READ FIRST
- + What You NEVER Do (Absolute Rules)
- + What You ALWAYS Do (Mandatory Steps)
- + Rule 1: NEVER ASSUME TEST COMPLETION
- + Rule 2: ALWAYS VALIDATE TEST OUTPUT
- + Rule 3: VALIDATE DEVICE LOGS FOR EXPECTED BEHAVIOR
- + Rule 4: SYSTEMATIC VALIDATION CHECKLIST
- + Step 1: Check for errors/exceptions FIRST
- + Step 2: Verify expected test actions (MOST IMPORTANT - proves test actually ran)
- + Step 3: Verify test completion marker
- + Step 4: Verify device logs show expected behavior
- + Step 5: Check screenshots were saved (if test captures them)
- + Step 6: Check exit code
- + 🚨 WARNING: "Test Completed Successfully" ≠ Test Actually Worked
- + Example of False Success
- + Check the logs:
- + Result: 20+ lines of "no such element" errors
- + The test looked for "InstructionLabel" which doesn't exist in MainPage
- + Appium never found ANY elements
- + Test script just gave up and exited with code 0
- + NO ACTUAL TESTING WAS PERFORMED
- + How to Detect False Success
- + Look for actual test actions in output
- + Purpose
- + When to Use Sandbox Testing
- + When NOT to Use Sandbox
- + Distinction: Code Review vs. Functional Testing
- + 🚨 Critical Requirements for Android Testing
- + Core Workflow
- + Step 1: Understand Issue (DO NOT Checkout PR Unless Instructed)
- + ONLY if user explicitly asks to test a PR:
- + Step 2: Create Test Scenario in Sandbox
- + Step 3: Test WITH PR Fix
- + How the Template Works
- + Copy the template
- + OPTIONAL: Add automated test logic in the TEST LOGIC section
- + If you don't add test logic, it just verifies launch and exits
- + Run the script
- + 🚨 CRITICAL: BuildAndRunSandbox.ps1 Script - ONLY Way to Deploy Sandbox
- + Script Location
- + Basic Usage
- + Android
- + iOS (auto-detects device)
- + iOS with specific device
- + What the Script Does Automatically
- + Requirements Before Running
- + 📝 Note for User
- + 1. Revert the PR fix files
- + 2. Rerun test - bug should appear
- + 3. Restore fix
- + 4. Rerun test - bug should be gone
- + 🔄 Iterative Testing Workflow (MANDATORY PROCESS)
- + The Required Loop
- + ❌ What NOT To Do
- + ✅ Correct Iteration Example
- + 1. Check what went wrong
- + 2. Check what DOES exist in MainPage
- + 3. Fix MainPage: Add AutomationIds
Commands
1 shared · 18 only in A · 9 only in B- − dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822
- − git checkout -b feature/issue-12345
- − git add .
- − git commit -m "Fix: Description of the change"
- − git push -u origin feature/issue-12345
- − git push
- − gh pr checkout 12345
- − dotnet cake
- − dotnet --version
- − gh pr checks
- − dotnet-public-maven
- − dotnet/android#10738
- − dotnet format analyzers
- − git fetch origin
- − git for-each-ref --sort=-version:refname --count=1 --format='%(refname:lstrip=3)' refs/remotes/origin/net*.0
- − gh pr checkout
- − dotnet test
- − dotnet-dnceng@dotnet-arcade-skills
- + gh pr checkout <PR_NUMBER>
- + git checkout main -- [list specific fix files from PR]
- + git checkout HEAD -- [fix files]
- + git checkout -- src/Controls/samples/Controls.Sample.Sandbox/
- + git checkout main
- + dotnet build
- + dotnet run
- + git checkout main -- [fix files]
- + dotnet build/run
- dotnet tool restore
Section tags
6 shared · 4 only in A · 2 only in B- − setup
- − lint-format
- − architecture
- − docs
- + build
- + deployment
- test
- code-style
- testing-strategy
- git-pr
- do-not
- agent-behaviour
Line diff
dotnet/maui · .github/copilot-instructions.md
@@ −1 @@
1---
2description: "Guidance for GitHub Copilot when working on the .NET MAUI repository."
3---
4
5# GitHub Copilot Development Environment Instructions
6
7This document provides specific guidance for GitHub Copilot when working on the .NET MAUI repository. It serves as context for understanding the project structure, development workflow, and best practices.
8
9## Code Review Instructions
10
11When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. This ensures proper documentation and helps maintain high-quality commit messages.
12
13## Repository Overview
14
15**.NET MAUI** is a cross-platform framework for creating mobile and desktop applications with C# and XAML. This repository contains the core framework code that enables development for Android, iOS, iPadOS, macOS, and Windows from a single shared codebase.
16
17### Key Technologies
18
19- **.NET SDK** - Version is **ALWAYS** defined in `global.json` at repository root
20 - **main branch**: Latest stable .NET version
21 - **Feature branches**: Each `netN.0` branch targets the .NET N SDK. By convention, the highest `netN.0` branch is the current development branch for new features and API changes.
22- **Cake build system** for compilation and packaging (`dotnet cake`)
23- **MSBuild** with custom build tasks (must build `Microsoft.Maui.BuildTasks.slnf` first)
24- **Testing frameworks**:
25 - **xUnit** - Unit tests (`*.UnitTests.csproj`)
26 - **NUnit** - UI tests (`TestCases.Shared.Tests`)
27 - **Appium WebDriver** - UI test automation
28
29## Development Environment Setup
30
31This guidance assumes:
32- Repository is already cloned and tools are restored (`dotnet tool restore` completed)
33- Build tasks are compiled (`Microsoft.Maui.BuildTasks.slnf` built successfully)
34- Correct .NET SDK version installed (verify with `dotnet --version` against `global.json`)
35
36### Platform-Specific Requirements
37
38- **Android**: OpenJDK 17 + Android SDK (install via `android` command after `dotnet tool restore`)
39- **iOS/macOS**: Xcode (current stable version)
40- **Windows**: Windows SDK
41
42## Project Structure
43
44### Important Directories
45- `src/Core/` - Core MAUI framework code
46- `src/Controls/` - UI controls and components
47- `src/Essentials/` - Platform APIs and essentials
48- `src/TestUtils/` - Testing utilities and infrastructure
49- `docs/` - Development documentation
50- `eng/` - Build engineering and tooling
51- `.github/` - GitHub workflows and configuration
52
53### Platform-Specific Code Organization
54- **Android** specific code is inside folders labeled `Android`
55- **iOS** specific code is inside folders labeled `iOS`
56- **MacCatalyst** specific code is inside folders named `MacCatalyst`
57- **Windows** specific code is inside folders named `Windows`
58
59### Platform-Specific File Extensions
60
61Platform-specific files use naming conventions to control compilation:
62
63**File extension patterns**:
64- `.windows.cs` - Windows TFM only
65- `.android.cs` - Android TFM only
66- `.ios.cs` - iOS and MacCatalyst TFMs (both)
67- `.maccatalyst.cs` - MacCatalyst TFM only (does NOT compile for iOS)
68
69**Important**: Both `.ios.cs` and `.maccatalyst.cs` files compile for MacCatalyst. There is no precedence mechanism that excludes one when the other exists.
70
71**Example**: If you have both `CollectionView.ios.cs` and `CollectionView.maccatalyst.cs`, both will compile for MacCatalyst builds. The `.maccatalyst.cs` file won't compile for iOS, but the `.ios.cs` file will compile for both iOS and MacCatalyst.
72
73### Sample Projects
74
75- `src/Controls/samples/Maui.Controls.Sample` - Full gallery sample with all controls and features
76- `src/Controls/samples/Maui.Controls.Sample.Sandbox` - Empty project for testing/reproduction
77- `src/Essentials/samples/Essentials.Sample` - Essentials API demonstrations (non-UI MAUI APIs)
78- `src/BlazorWebView/samples/` - BlazorWebView sample applications
79
80## Development Workflow
81
82### Testing
83
84Major test projects:
85- **Core**: `src/Core/tests/UnitTests/Core.UnitTests.csproj`
86- **Essentials**: `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj`
87- **Controls**: `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj`
88- **XAML**: `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj`
89
90Find all tests: `find . -name "*.UnitTests.csproj"`
91
92### CI Pipelines (Azure DevOps)
93
94When referencing or triggering CI pipelines, use these current pipeline names:
95
96| Pipeline | Name | Purpose |
97|----------|------|---------|
98| Overall CI | `maui-pr` | Full PR validation build |
99| Device Tests | `maui-pr-devicetests` | Helix-based device tests |
100| UI Tests | `maui-pr-uitests` | Appium-based UI tests |
101
102**⚠️ Old pipeline names** (e.g., `MAUI-UITests-public`, `MAUI-public`) are **outdated** and should NOT be used. Always use the names above.
103
104### Investigating CI Failures
105
106**🚨 ALWAYS use the `azdo-build-investigator` skill when investigating CI failures or assessing merge readiness.** Its instructions direct you to invoke the `ci-analysis` skill first for the core investigation workflow, then apply MAUI-specific corrections (correct pipeline names, XHarness quirks, binlog guidance).
107
108Do NOT default to manually querying AzDO APIs or rely solely on `gh pr checks` pass/fail counts.
109
110**When to use it:**
111- "How does CI look?" / "Is CI green?" / "Can we merge?"
112- "What's failing?" / "Are these known failures?"
113- "Is this PR safe to merge?" / "Any CI concerns?"
114- After any PR push to verify the build
115
116**Verifying specific tests:** When asked "did test X pass?" or "did the new test run?", query the **actual AzDO test results** — do NOT infer whether a test ran by inspecting code attributes. Class-level traits, base class categories, and assembly-level attributes can all cause a test to run even when the method itself has no visible category. Check the evidence, not the code.
117
118**Anti-pattern:** Writing ad-hoc scripts to parse AzDO build timelines. The skills handle Helix work item details, known issue cross-referencing, and test result aggregation that manual approaches miss.
119
120### Gradle / Maven Dependency Failures (CFSClean)
121
122The official CI build uses CFSClean network isolation which blocks `repo.maven.apache.org`. All Gradle/Maven dependencies resolve through the `dotnet-public-maven` Azure Artifacts feed.
123
124**If CI fails with Gradle 401 errors** like `"No local versions of package"` or `"Please provide authentication to save package from upstream"`, it means a Maven package hasn't been ingested into the feed yet. **Fix:** run `./eng/ingest-maven-deps.sh` locally to pre-populate the feed. See `src/Core/AndroidNative/settings.gradle` for details.
125
126**Do NOT upgrade Gradle past 8.x** — the Android SDK's `net.android.init.gradle.kts` is incompatible with Gradle 9.x (`dotnet/android#10738`).
127
128### Code Formatting
129
130Always format code before committing:
131
132```bash
133dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822
134```
135
136## Contribution Guidelines
137
138### Handling Existing PRs for Assigned Issues
139
140**🚨 CRITICAL REQUIREMENT: Always develop your own solution first, then compare with existing PRs.**
141
1421. **Develop your own solution first** - Analyze the issue independently and design your approach without looking at existing PRs
1432. **Search for existing PRs** - After developing your solution, search for open PRs addressing the same issue
1443. **Compare and evaluate** - Examine existing PR approaches and decide which solution better addresses the issue
1454. **Document your decision** - In your PR description, compare your solution to existing PRs and explain why you chose your approach, including concerns with alternatives
1465. **Improve either solution** - Whether using your solution or an existing one, enhance with better tests, code quality, error handling, or documentation
147
148### Auto-Generated Files (Never Commit)
149
150These files are auto-generated and must NOT be committed:
151- `cgmanifest.json` - Generated during CI builds
152- `templatestrings.json` - Auto-generated localization
153
154**For AI agents:** Always reset changes to these files before committing.
155
156### PublicAPI.Unshipped.txt File Management
157
158When working with public API changes:
159- **Never disable analyzers** to bypass PublicAPI.Unshipped.txt issues
160- **Always add correct API entries** to PublicAPI.Unshipped.txt files
161- **Use `dotnet format analyzers`** if having trouble
162- **If files are incorrect**: Revert all changes, then add only the necessary new API entries
163
164### Branching
165- `main` - For bug fixes without API changes
166- The highest `netN.0` branch (by convention) - For new features and API changes. To find it, run `git fetch origin` then: `git for-each-ref --sort=-version:refname --count=1 --format='%(refname:lstrip=3)' refs/remotes/origin/net*.0`
167
168### Git Workflow (Copilot CLI Rules)
169
170**🚨 CRITICAL Git Rules for Copilot CLI:**
171
1721. **NEVER commit directly to `main`** - Always create a feature branch for your work. Direct commits to `main` are strictly prohibited.
173
1742. **When amending an existing PR, work on the PR's branch directly** - Do NOT create a separate branch off a PR branch. The PR branch already IS a feature branch. Creating a new branch off it means CI won't run on the original PR, defeating the purpose. Use `gh pr checkout` to switch to the PR branch, make your changes, commit, **then** ask before pushing so the user can review locally first.
175
1763. **Do NOT rebase, squash, or force-push** unless explicitly requested by the user. These operations rewrite git history and can cause problems for other contributors. Default behavior should be regular commits and pushes.
177
178**Safe Git Workflow:**
179```bash
180# Create a feature branch (NEVER work directly on main)
181git checkout -b feature/issue-12345
182
183# Make commits normally
184git add .
185git commit -m "Fix: Description of the change"
186
187# Push to remote (for new branches)
188git push -u origin feature/issue-12345
189
190# For subsequent pushes on the same branch
191git push
192```
193
194**When asked to update an existing PR:**
195```bash
196# Check out the PR branch directly (do NOT create a new branch off it)
197gh pr checkout 12345
198
199# Make fixes and commit to the PR branch
200git add .
201git commit -m "Fix: Description of the change"
202```
2031. **STOP and ask the user** before pushing: "Changes are committed locally. Would you like me to push these changes to the PR?"
2042. Exception: If the user's instructions explicitly include pushing, proceed without asking.
205
206### Documentation
207- Update XML documentation for public APIs
208- Follow existing code documentation patterns
209- Update relevant docs in `docs/` folder when needed
210
211### Opening PRs
212
213All PRs are required to have this at the top of the description:
214
215```
216<!-- Please let the below note in for people that find this PR -->
217> [!NOTE]
218> Are you waiting for the changes in this PR to be merged?
219> It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you!
220```
221
222Always put that at the top, without the block quotes. Without it, users will NOT be able to try the PR and your work will have been in vain!
223
224
225
226## Custom Agents and Skills
227
228The repository includes specialized custom agents and reusable skills for specific tasks.
229
230### Skills vs Agents
231
232| Aspect | Skills | Agents |
233|--------|--------|--------|
234| **Invoke** | `/skill-name` or direct request | Delegate to agent |
235| **Output** | Analysis, recommendations | Actions, changes applied |
236| **Interaction** | Interactive discussion | Autonomous workflow |
237| **Example** | `/learn-from-pr` → recommendations | learn-from-pr agent → applies changes |
238
239### Available Custom Agents
240
2411. **pr** - Sequential 4-phase workflow for reviewing and working on PRs
242 - **Use when**: A PR already exists and needs review or work, OR an issue needs a fix
243 - **Capabilities**: PR review, test verification, fix exploration, alternative comparison
244 - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX"
245 - **Do NOT use for**: Just running tests manually → Use `sandbox-agent`
246
2472. **write-tests-agent** - Agent for writing tests. Determines test type (UI vs XAML) and invokes the appropriate skill (`write-ui-tests`, `write-xaml-tests`)
248 - **Use when**: Creating new tests for issues or PRs
249 - **Capabilities**: Test type determination (UI and XAML), skill invocation, test verification
250 - **Trigger phrases**: "write tests for #XXXXX", "create tests", "add test coverage"
251
2523. **sandbox-agent** - Specialized agent for working with the Sandbox app for testing, validation, and experimentation
253 - **Use when**: User wants to manually test PR functionality or reproduce issues
254 - **Capabilities**: Sandbox app setup, Appium-based manual testing, PR functional validation
255 - **Trigger phrases**: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX", "try out in Sandbox"
256 - **Do NOT use for**: Code review (use pr agent), writing automated tests (use write-tests-agent)
257
2584. **learn-from-pr** - Extracts lessons from PRs and applies improvements to the repository
259 - **Use when**: After complex PR, want to improve instruction files/skills based on lessons learned
260 - **Capabilities**: Analyzes PR, identifies failure modes, applies improvements to instruction files, skills, code comments
261 - **Trigger phrases**: "learn from PR #XXXXX and apply improvements", "improve repo based on what we learned", "update skills based on PR"
262 - **Output**: Applied changes to instruction files, skills, architecture docs, code comments
263 - **Do NOT use for**: Analysis only without applying changes → Use `/learn-from-pr` skill instead
264
2655. **release-readiness-agent** - Assesses ship-readiness for a .NET MAUI release branch — both **SR** (`release/*-srN`) and **Preview** (`release/*-previewN`)
266 - **Use when**: A release (SR or Preview) is approaching ship date and you need a synthesized verdict with WorkIQ/MCP enrichment on top of the deterministic report — **or** for a portfolio question across all active releases ("status on releases", "what needs attention across releases") where the user may not know which releases exist
267 - **Capabilities**: Resolves the branch (SR or Preview) from natural language, picks the right script (`Get-ReleaseReadiness.ps1` for SR, `Get-PreviewReadiness.ps1` for Preview), enriches `rejected-from-sr` candidates with WorkIQ context (SR lane), patches `UNKNOWN` ship-check rows via MCP (`maestro_default_channels`, `maestro_builds`), presents an overall verdict
268 - **Trigger phrases**: "is SR7 ready to ship", "release readiness for release/10.0.1xx-sr7", "survey the SR8 branch", "how does net11 preview6 look", "is preview6 ready to cut", "release readiness for release/11.0.1xx-preview6" — **plus portfolio / cross-release questions with no specific release named**: "give me a status on releases", "release status overview", "what's the status across all releases", "what needs attention across releases", "what's next for MAUI releases"
269 - **Output**: Verdict (Ready / Conditionally Ready / Not Ready) + per-candidate classification (SR) or per-section table (Preview) + actionable next steps
270 - **Do NOT use for**: Programmatic / scripted consumers that just need the raw JSON — use the `release-readiness` skill directly. Reviewing a single PR (use **pr**). Running tests manually (use **sandbox-agent**).
271
272### Reusable Skills
273
274Skills are modular capabilities that can be invoked directly or used by agents. Located in `.github/skills/`:
275
276#### User-Facing Skills
277
2781. **pr-review** (`.github/skills/pr-review/SKILL.md`)
279 - **Purpose**: End-to-end PR review orchestrator — 3 phases: pr-preflight, try-fix, pr-report. Gate runs separately before this skill via Review-PR.ps1.
280 - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX"
281 - **Capabilities**: Multi-model fix exploration, alternative comparison, PR review recommendation
282 - **Do NOT use for**: Just running tests manually → Use `sandbox-agent`
283 - **Phase instructions** (in `.github/pr-review/`):
284 - `pr-preflight.md` — Context gathering from issue/PR
285 - `pr-report.md` — Final recommendation
286 - **Phase skill**: `try-fix` — Multi-model fix exploration
287 - **Note**: Gate (test verification) runs as a script step in `Review-PR.ps1` before this skill is invoked. Gate result is passed in the prompt.
288
2892. **issue-triage** (`.github/skills/issue-triage/SKILL.md`)
290 - **Purpose**: Query and triage open issues that need milestones, labels, or investigation
291 - **Trigger phrases**: "find issues to triage", "show me old Android issues", "what issues need attention"
292 - **Scripts**: `init-triage-session.ps1`, `query-issues.ps1`, `record-triage.ps1`
293
2942. **find-reviewable-pr** (`.github/skills/find-reviewable-pr/SKILL.md`)
295 - **Purpose**: Finds open PRs in dotnet/maui and dotnet/docs-maui that need review
296 - **Trigger phrases**: "find PRs to review", "show milestoned PRs", "find partner PRs"
297 - **Scripts**: `query-reviewable-prs.ps1`
298 - **Categories**: P/0, milestoned, partner, community, recent, docs-maui
299
3003. **pr-finalize** (`.github/skills/pr-finalize/SKILL.md`)
301 - **Purpose**: Verifies PR title and description match actual implementation, AND performs code review for best practices before merge.
302 - **Trigger phrases**: "finalize PR #XXXXX", "check PR description for #XXXXX", "review commit message"
303 - **Used by**: Before merging any PR, when description may be stale
304 - **Note**: Does NOT require agent involvement or session markdown - works on any PR
305 - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` - only post comments. Approval is a human decision.
306
3074. **code-review** (`.github/skills/code-review/SKILL.md`)
308 - **Purpose**: Reviews PR code changes for correctness, safety, and consistency with MAUI conventions. Walks through a MAUI-specific checklist covering handler lifecycle, platform code, safe area, threading, public API, and test patterns.
309 - **Trigger phrases**: "review code for PR #XXXXX", "code review PR #XXXXX", "review this PR's code"
310 - **Note**: Standalone skill — uses independence-first assessment (reads code before PR description to avoid anchoring bias). Can be used by any agent or invoked directly.
311 - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` — only post comments. Approval is a human decision.
312
3135. **learn-from-pr** (`.github/skills/learn-from-pr/SKILL.md`)
314 - **Purpose**: Analyzes completed PR to identify repository improvements (analysis only, no changes applied)
315 - **Trigger phrases**: "what can we learn from PR #XXXXX?", "how can we improve agents based on PR #XXXXX?"
316 - **Used by**: After complex PRs, when agent struggled to find solution
317 - **Output**: Prioritized recommendations for instruction files, skills, code comments
318 - **Note**: For applying changes automatically, use the learn-from-pr agent instead
319
3206. **write-ui-tests** (`.github/skills/write-ui-tests/SKILL.md`)
321 - **Purpose**: Creates UI tests for GitHub issues and verifies they reproduce the bug
322 - **Trigger phrases**: "write UI tests for #XXXXX", "create UI test for issue", "add UI test coverage"
323 - **Output**: Test files that fail without fix, pass with fix
324
3257. **write-xaml-tests** (`.github/skills/write-xaml-tests/SKILL.md`)
326 - **Purpose**: Creates XAML unit tests for XAML parsing, compilation, and source generation
327 - **Trigger phrases**: "write XAML tests for #XXXXX", "test XamlC behavior", "reproduce XAML parsing bug"
328 - **Output**: Test files for Controls.Xaml.UnitTests
329
3309. **verify-tests-fail-without-fix** (`.github/skills/verify-tests-fail-without-fix/SKILL.md`)
331 - **Purpose**: Verifies tests catch the bug before fix and pass with fix. Auto-detects test type (UI, device, unit, XAML) and dispatches to the appropriate runner.
332 - **Two modes**: Verify failure only (test creation) or full verification (test + fix)
333 - **Used by**: After creating tests, before considering PR complete
334
33510. **run-integration-tests** (`.github/skills/run-integration-tests/SKILL.md`)
336 - **Purpose**: Build, pack, and run .NET MAUI integration tests locally
337 - **Trigger phrases**: "run integration tests", "test templates locally", "run macOSTemplates tests", "run RunOniOS tests"
338 - **Categories**: Build, WindowsTemplates, macOSTemplates, Blazor, MultiProject, Samples, AOT, RunOnAndroid, RunOniOS
339 - **Note**: **ALWAYS use this skill** instead of manual `dotnet test` commands for integration tests
340
34111. **dependency-flow** (`.github/skills/dependency-flow/SKILL.md`)
342 - **Purpose**: MAUI-specific dependency flow rules, channel conventions, and feed lookup workflows
343 - **Trigger phrases**: "feeds for .NET MAUI X.Y.Z", "where is MAUI build", "promote build to public feed", "what channels is MAUI on", "subscription health for MAUI"
344 - **Wraps**: `maestro-cli` skill (from `dotnet-dnceng@dotnet-arcade-skills` plugin) and maestro MCP tools
345 - **Note**: Provides MAUI-specific guardrails on top of core Maestro/darc operations — channel naming, safety deny-list, input validation, and prompt injection defense
346
34712. **release-readiness** (`.github/skills/release-readiness/SKILL.md`)
348 - **Purpose**: Deterministic ship-readiness engine for .NET MAUI release branches — both **SR** (`release/*-srN`) and **Preview** (`release/*-previewN`). Surveys CI, computes what's actually shipping, classifies open regressions, identifies port candidates and rejected backports
349 - **Trigger phrases**: "release readiness for SRN", "is SR7 ready to ship", "survey the SR branch", "release readiness for preview6", "how does preview6 look (deterministic)", "status across all releases" (reads the live `[Release Readiness]` tracker issues by body marker — no survey re-run needed)
350 - **Scripts**: `Get-ReleaseReadiness.ps1` (SR lane), `Get-PreviewReadiness.ps1` (Preview lane), `Find-ReleaseReadinessTrackers.ps1` (tracker discovery)
351 - **Output**: JSON + Markdown report, list of source PRs, classification of regression issues (in-sr-active, rejected-from-sr, no-fix-yet, etc.)
352 - **Note**: Deterministic and reproducible — no MCP, no LLM judgment. Use **this skill directly** when you need raw output for a script, dashboard, cron job, or programmatic consumer. For natural-language verdict synthesis with WorkIQ enrichment, use the **`release-readiness-agent`** instead.
353
354#### Internal Skills (Used by Agents)
355
35613. **try-fix** (`.github/skills/try-fix/SKILL.md`)
357 - **Purpose**: Proposes ONE independent fix approach, applies it, tests, records result with failure analysis, then reverts
358 - **Used by**: pr agent Phase 3 (Fix phase) - rarely invoked directly by users
359 - **Behavior**: Reads prior attempts to learn from failures. Max 5 attempts per session.
360 - **Output**: Updates session markdown with attempt results and failure analysis
361
362### Using Custom Agents
363
364**Delegation Policy**: When user request matches agent trigger phrases, **ALWAYS delegate to the appropriate agent immediately**. Do not ask for permission or explain alternatives unless the request is ambiguous.
365
366**Examples of correct delegation**:
367- User: "Review PR #12345" → Immediately invoke **pr** agent
368- User: "Test this PR" → Immediately invoke **sandbox-agent**
369- User: "Fix issue #67890" (no PR exists) → Suggest using `/delegate` command
370- User: "Write tests for issue #12345" → Immediately invoke **write-tests-agent**
371- User: "Is SR7 ready to ship?" → Immediately invoke **release-readiness-agent**
372- User: "How does net11 preview6 look?" → Immediately invoke **release-readiness-agent**
373- User: "Give me a status on releases / what needs attention across releases?" → Immediately invoke **release-readiness-agent** (portfolio mode — it enumerates active releases by reading the `[Release Readiness]` tracker issues; don't ask "which release?")
374- User: "Give me the raw release-readiness JSON for SR8" → Use the **release-readiness** skill directly (no enrichment needed)
375
376**When NOT to delegate**:
377- User asks "What does PR #12345 do?" → Informational query, handle yourself
378- User asks "How do I test PRs?" → Documentation query, handle yourself
379- User has follow-up questions after agent completes → Continue the conversation yourself
dotnet/maui · .github/instructions/sandbox.instructions.md
@@ +1 @@
1---
2description: "Comprehensive guide for working with the .NET MAUI Sandbox app for testing, validation, and experimentation"
3applyTo: "src/Controls/samples/Controls.Sample.Sandbox/**"
4---
5
6# Sandbox Testing Guide
7
8Comprehensive guide for working with the .NET MAUI Sandbox app for manual testing, PR validation, issue reproduction, and experimentation with MAUI features.
9
10## When This Applies
11
12This guide applies when you:
13- Work with files in `src/Controls/samples/Controls.Sample.Sandbox/`
14- User asks to "test this PR" or "validate PR #XXXXX" in Sandbox
15- User asks to "reproduce issue #XXXXX" in Sandbox
16- User wants to deploy to iOS/Android for manual testing
17- User mentions Sandbox app by name in testing context
18
19## 🚨 CRITICAL VALIDATION RULES - READ FIRST
20
21**YOU MUST FOLLOW THESE RULES WHEN RUNNING SANDBOX TESTS:**
22
23### What You NEVER Do (Absolute Rules)
24
25- ❌ **NEVER** assume test completion without validation
26- ❌ **NEVER** claim success based on HTTP 200 responses alone (element found ≠ test completed)
27- ❌ **NEVER** skip the mandatory validation checklist
28- ❌ **NEVER** proceed without verifying device logs show expected behavior
29- ❌ **NEVER** assume Appium connection means test finished
30- ❌ **NEVER** claim button was tapped without checking device logs
31- ❌ **NEVER** switch branches (e.g., `git checkout main`) during reproduction - stay on current branch
32
33### What You ALWAYS Do (Mandatory Steps)
34
35- ✅ **ALWAYS** save full output to file for analysis
36- ✅ **ALWAYS** check for errors/exceptions FIRST before claiming success
37- ✅ **ALWAYS** verify "Test completed" marker appears in output
38- ✅ **ALWAYS** verify expected test actions in logs (Tapping, Screenshot, etc.)
39- ✅ **ALWAYS** check device logs for Console.WriteLine markers (e.g., "SANDBOX: ...")
40- ✅ **ALWAYS** verify artifacts exist (screenshots, if test captures them)
41
42### Rule 1: NEVER ASSUME TEST COMPLETION
43- ❌ **DO NOT** assume the test completed successfully just because Appium connected
44- ❌ **DO NOT** assume success based on HTTP 200 responses (element found ≠ test completed)
45- ✅ **DO** verify test completion by checking for completion markers in output
46- ✅ **DO** search for "Test completed", "═══════", or final summary messages
47
48### Rule 2: ALWAYS VALIDATE TEST OUTPUT
49After running BuildAndRunSandbox.ps1, you MUST:
501. **Save full output to file**: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios > CustomAgentLogsTmp/Sandbox/build-run-output.log 2>&1`
512. **Check for errors FIRST**: `grep -E "ERROR|Exception|failed" CustomAgentLogsTmp/Sandbox/build-run-output.log`
523. **Verify completion markers**: `grep "Test completed\|══════" CustomAgentLogsTmp/Sandbox/build-run-output.log`
534. **Check for expected actions**: `grep "Tapping\|Screenshot saved\|switched to" CustomAgentLogsTmp/Sandbox/build-run-output.log`
54
55### Rule 3: VALIDATE DEVICE LOGS FOR EXPECTED BEHAVIOR
56- ✅ **DO** check device logs confirm your expected test actions happened
57- ✅ **DO** grep for your Console.WriteLine markers (e.g., "SANDBOX.*CLICKED")
58- ❌ **DO NOT** claim the test worked without verifying device logs show the action
59
60### Rule 4: SYSTEMATIC VALIDATION CHECKLIST
61After EVERY test run, verify ALL of these **IN THIS ORDER**:
62
63```bash
64# Step 1: Check for errors/exceptions FIRST
65grep -iE "error|exception|failed" CustomAgentLogsTmp/Sandbox/build-run-output.log | grep -v "no such element" | head -20
66
67# Step 2: Verify expected test actions (MOST IMPORTANT - proves test actually ran)
68grep -E "Tapping|Screenshot saved|Found.*element|Clicking|Entering text" CustomAgentLogsTmp/Sandbox/build-run-output.log
69
70# Step 3: Verify test completion marker
71grep "Test completed" CustomAgentLogsTmp/Sandbox/build-run-output.log
72
73# Step 4: Verify device logs show expected behavior
74grep "SANDBOX" CustomAgentLogsTmp/Sandbox/android-device.log # or ios-device.log
75
76# Step 5: Check screenshots were saved (if test captures them)
77ls -lh CustomAgentLogsTmp/Sandbox/*.png
78
79# Step 6: Check exit code
80echo $? # Should be 0 for success
81```
82
83**CRITICAL**: If Step 2 shows NO test actions, the test didn't actually run even if it "completed successfully". Update your Appium test and rerun.
84
85**If ANY of these checks fail, the test DID NOT complete successfully. Investigate and fix before proceeding.**
86
87---
88
89## 🚨 WARNING: "Test Completed Successfully" ≠ Test Actually Worked
90
91**CRITICAL UNDERSTANDING**: The message "✅ Test completed successfully" only means:
92- ✅ Appium test script finished running without crashing
93- ✅ Script exit code was 0
94
95**It does NOT mean**:
96- ❌ Appium found your UI elements
97- ❌ Buttons were clicked
98- ❌ Navigation happened
99- ❌ Your test scenario actually ran
100
101### Example of False Success
102
103**What you see in output**:
104```
105✅ Test completed successfully
106
107╔═══════════════════════════════════════════════════════════╗
108║ Test Summary ║
109╠═══════════════════════════════════════════════════════════╣
110║ Platform: ANDROID ║
111║ Device: emulator-5554 ║
112║ Result: SUCCESS ✅ ║
113╚═══════════════════════════════════════════════════════════╝
114```
115
116**What actually happened**:
117```bash
118# Check the logs:
119grep "no such element" CustomAgentLogsTmp/Sandbox/build-run-output.log
120# Result: 20+ lines of "no such element" errors
121
122# The test looked for "InstructionLabel" which doesn't exist in MainPage
123# Appium never found ANY elements
124# Test script just gave up and exited with code 0
125# NO ACTUAL TESTING WAS PERFORMED
126```
127
128### How to Detect False Success
129
130**MANDATORY check after EVERY "successful" test**:
131```bash
132# Look for actual test actions in output
133grep -E "Tapping|Clicking|Found element|Screenshot saved" CustomAgentLogsTmp/Sandbox/build-run-output.log
134```
135
136**If grep returns NOTHING → FALSE SUCCESS**:
137- Test didn't actually do anything
138- Template test is looking for elements that don't exist
139- You MUST update `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` to match your MainPage
140- Rerun BuildAndRunSandbox.ps1 after updating test
141
142**If grep returns multiple lines → REAL SUCCESS**:
143- Test found elements and interacted with them
144- Proceed with full validation checklist
145
146---
147
148## Purpose
149
150Work with the Sandbox app for manual testing, PR validation, issue reproduction, and experimentation with MAUI features.
151
152## When to Use Sandbox Testing
153
154- ✅ User asks to "test this PR" (functional testing, not code review)
155- ✅ User asks to "validate PR #XXXXX" or "validate PR #XXXXX in Sandbox"
156- ✅ User asks to "reproduce issue #XXXXX" or "try out issue #XXXXX"
157- ✅ User asks to "try out" or "experiment with" a feature in Sandbox
158- ✅ PR modifies core MAUI functionality (controls, layouts, platform code)
159- ✅ Need to manually verify a fix works on device/simulator
160- ✅ Need to create a quick test scenario for hands-on validation
161
162## When NOT to Use Sandbox
163
164- ❌ User asks to "review PR #XXXXX" → Use **pr** agent for code review
165- ❌ User asks to "write tests" or "create automated tests" → Use **write-tests-agent**
166- ❌ User asks to "validate the UI tests" or "verify test quality" → Review test code instead
167- ❌ User asks to "fix issue #XXXXX" (no PR exists) → Suggest `/delegate` command
168- ❌ PR only adds documentation (no code changes to test)
169- ❌ PR only modifies build scripts (no functional changes)
170
171## Distinction: Code Review vs. Functional Testing
172
173**Code Review** (pr-review skill):
174- Analyzes code quality, patterns, best practices
175- Reviews test coverage and correctness
176- Checks for potential bugs or issues in the code itself
177- Trigger: "review PR", "work on PR"
178
179**Functional Testing** (sandbox-agent):
180- Builds and deploys PR to device/simulator
181- Manually validates the fix works as expected
182- Reproduces issues and verifies they're resolved
183- Trigger: "test this PR", "validate PR in Sandbox", "reproduce issue"
184
185## 🚨 Critical Requirements for Android Testing
186
187**ANDROID-ONLY REQUIREMENT - appium:noReset**
188
189⚠️ **This ONLY applies to Android, NOT iOS**
190
191When testing on Android, the Appium test script **MUST** have this capability:
192
193```csharp
194// ANDROID ONLY - Do NOT add this for iOS
195if (PLATFORM == "android")
196{
197 options.AddAdditionalAppiumOption("appium:noReset", true);
198}
199```
200
201**Why this is critical for Android:**
202- Without `noReset`, Appium clears app data between runs
203- This breaks .NET MAUI's Fast Deployment mechanism on Android
204- App crashes with: `"No assemblies found in '.../__override__/...' ... Assuming this is part of Fast Deployment. Exiting..."`
205- The app will crash immediately on launch before any test can run
206
207**iOS does NOT need this** - iOS deployment works differently and doesn't use Fast Deployment
208
209**Where to set it:**
210- Template: `.github/scripts/templates/RunWithAppiumTest.template.cs` (line ~68, Android section only)
211- Active test: `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` (Android section only)
212
213**Platform detection is automatic** - The template automatically detects Android vs iOS from the UDID format, so you don't need to manually set the platform. The `if (PLATFORM == "android")` block will execute automatically when testing on Android.
214
215**⚠️ NEVER REMOVE THIS CAPABILITY FROM ANDROID** - All Android tests depend on it
216
217---
218
219## Core Workflow
220
221**🚨 CRITICAL RULES FOR ENTIRE WORKFLOW:**
222- **ALWAYS use BuildAndRunSandbox.ps1 script** for building, deploying, and testing
223- **NEVER use manual `dotnet build`, `adb`, or `xcrun` commands**
224- **NEVER switch branches during reproduction** - stay on the current branch
225- **ALWAYS stop and ask user if you cannot reproduce** - do not try alternative branches
226- The script handles device detection, build, deployment, and test execution automatically
227- See "BuildAndRunSandbox.ps1 Script" section below for full details
228
229---
230
231### Step 1: Understand Issue (DO NOT Checkout PR Unless Instructed)
232
233**⚠️ IMPORTANT**: Only checkout a PR if the user explicitly asks you to test a specific PR. For general issue reproduction, work on the current branch.
234
235```bash
236# ONLY if user explicitly asks to test a PR:
237gh pr checkout <PR_NUMBER>
238```
239
240**Understand the issue thoroughly:**
241- Read issue report or PR description
242- Identify what bug needs to be reproduced
243- Note affected platforms
244- Look for reproduction steps in the issue
245- If testing a PR: Review PR changes to understand the fix
246
247---
248
249### Step 2: Create Test Scenario in Sandbox
250
251**Choose test scenario source (in priority order):**
252
2531. **From Issue Reproduction** (Preferred)
254 - Look for "Reproduction" or "Steps to Reproduce" in the linked issue
255 - Use the exact scenario the user reported
256 - This proves you're testing what the user experienced
257
2582. **From PR's UI Tests** (Alternative)
259 - Check if PR includes files in `TestCases.HostApp/Issues/IssueXXXXX.*`
260 - Adapt the test page code to Sandbox
261 - Simplify if needed for manual testing
262
2633. **Create Your Own** (Last Resort)
264 - If no repro available, design scenario based on PR changes
265 - Focus on the specific code paths modified by the fix
266 - Keep it simple and focused
267
268**Files to modify**:
269- `src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml[.cs]` - UI and code for reproduction
270- `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` - Appium test script (MANDATORY - see setup below)
271
272**Setting up the Appium test file (MANDATORY):**
273
274🚨 **CRITICAL**: Update Appium test BEFORE running script. Template will give FALSE SUCCESS otherwise.
275
2761. **Create test file**:
277 ```bash
278 mkdir -p CustomAgentLogsTmp/Sandbox
279 cp .github/scripts/templates/RunWithAppiumTest.template.cs CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs
280 ```
281
2822. **Update test to match MainPage**:
283 - Check AutomationIds: `grep AutomationId MainPage.xaml`
284 - Update test to use those IDs (not template defaults)
285 - Add test logic: tap buttons, verify labels
286 - Add Console.WriteLine markers for debugging
287
2883. **Example**:
289 ```bash
290 # Check MainPage
291 grep 'AutomationId=' MainPage.xaml
292 # Update test: App.WaitForElement("NavigateButton");
293 ```
294
295**Checklist**:
296- ✅ Add AutomationIds to MainPage.xaml elements
297- ✅ Update RunWithAppiumTest.cs to match
298- ✅ Add SANDBOX markers for debugging
299
300**🚨 CRITICAL - Document Your Test Scenario:**
301
302You MUST include in your final report:
303- ✅ **Source**: Where did the test scenario come from? (issue reproduction / PR UITest / custom)
304- ✅ **Why**: Why did you choose that source? (e.g., "Issue #XXXXX provides detailed repro steps")
305- ✅ **What**: What specific actions does your test perform? (e.g., "Tap button → verify label changes to 'Success'")
306- ✅ **Expected**: What behavior should occur? (from issue description or PR changes)
307
308Without this documentation, user cannot verify you tested the right thing.
309
310---
311
312### Step 3: Test WITH PR Fix
313
314**Platform Selection Decision Tree:**
315
316Follow this flowchart in order - stop at the first match:
317
318```
319┌─────────────────────────────────────────────────────────────────┐
320│ 1. Does PR title have platform tag? [Android], [iOS], etc. │
321│ YES → Test that platform ONLY │
322│ NO → Continue to step 2 │
323├─────────────────────────────────────────────────────────────────┤
324│ 2. Are ALL modified files in platform-specific paths? │
325│ (Platform/Android/, Platform/iOS/, *.Android.cs, etc.) │
326│ YES → Test that platform ONLY │
327│ NO → Continue to step 3 │
328├─────────────────────────────────────────────────────────────────┤
329│ 3. Does issue report mention a specific platform? │
330│ YES (one platform) → Test that platform ONLY │
331│ YES (multiple) → Test Android + iOS │
332│ NO → Continue to step 4 │
333├─────────────────────────────────────────────────────────────────┤
334│ 4. Is this high-risk cross-platform code? │
335│ (Controls/, Core/, layout, navigation, critical controls) │
336│ YES → Test Android + iOS │
337│ NO → Test Android ONLY (default - faster) │
338└─────────────────────────────────────────────────────────────────┘
339```
340
341**Platform-specific path indicators:**
342- `Platform/Android/` or `Platform/iOS/` → Platform-specific
343- Files with `.Android.`, `.iOS.`, `.MacCatalyst.` in name → Platform-specific
344- `Controls/`, `Core/` without platform subfolders → Cross-platform
345
346**Hard rule:** Never test more than 2 platforms unless user explicitly requests it.
347
348**Run Test on Specific iOS Device/Version:**
349
350When user requests a specific iOS version or device:
351
3521. **Find the UDID for that device/version combination**:
353 ```bash
354 # Example: Find iPhone Xs with iOS 18.5
355 UDID=$(xcrun simctl list devices available --json | jq -r '
356 .devices
357 | to_entries
358 | map(select(.key | contains("iOS-18-5")))
359 | map(.value)
360 | flatten
361 | map(select(.name == "iPhone Xs"))
362 | first
363 | .udid
364 ')
365
366 echo "Found UDID: $UDID"
367 ```
368
3692. **Pass the UDID to the script**:
370 ```bash
371 pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios -DeviceUdid "$UDID"
372 ```
373
374**Examples:**
375- **"Run on iOS 18.5"** → Find iPhone Xs with iOS 18.5, get UDID, pass to script
376- **"Run on iPhone 15"** → Find iPhone 15 (any iOS), get UDID, pass to script
377- **"Run on iPhone 16 Pro with iOS 18.0"** → Find iPhone 16 Pro with iOS 18.0, get UDID, pass to script
378
379---
380
381## How the Template Works
382
383**The template ALWAYS does the same thing:**
384
3851. ✅ Verifies app launched successfully (WaitForElement)
3862. ✅ Optionally runs automated UI tests (if you add them)
3873. ✅ Exits WITHOUT closing the app (stays running for manual validation)
388
389**Usage:**
390```bash
391# Copy the template
392cp .github/scripts/templates/RunWithAppiumTest.template.cs CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs
393
394# OPTIONAL: Add automated test logic in the TEST LOGIC section
395# If you don't add test logic, it just verifies launch and exits
396
397# Run the script
398pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios
399```
400
401**Result:**
402- App launches and stays running
403- You can manually validate in the simulator
404- Test script exits without closing the app
405
406---
407
408## 🚨 CRITICAL: BuildAndRunSandbox.ps1 Script - ONLY Way to Deploy Sandbox
409
410**YOU MUST ALWAYS USE THIS SCRIPT. NEVER USE MANUAL `dotnet build`, `adb`, or `xcrun` COMMANDS.**
411
412### Script Location
413`.github/scripts/BuildAndRunSandbox.ps1`
414
415### Basic Usage
416```powershell
417# Android
418pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform Android
419
420# iOS (auto-detects device)
421pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform iOS
422
423# iOS with specific device
424pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform iOS -DeviceUdid "YOUR-DEVICE-UDID"
425```
426
427### What the Script Does Automatically
428- ✅ **Device detection and boot** - Finds and boots simulator/emulator
429- ✅ **UDID extraction** - Sets DEVICE_UDID environment variable
430- ✅ **Fresh app build** - Builds Sandbox project for target platform
431- ✅ **App deployment** - Installs and launches app
432- ✅ **Appium server management** - Starts/stops Appium automatically
433- ✅ **Log capture** - Saves device and Appium logs to `CustomAgentLogsTmp/Sandbox/`
434- ✅ **Test execution** - Runs your Appium test script
435
436### Requirements Before Running
437Copy and update test file (see Step 2 above). Template looks for "InstructionLabel" which doesn't exist - update first!
438
439**🚨 POST-TEST VALIDATION (MANDATORY):**
440
441After script completes, run Rule 4 validation checklist (see above). If ANY check fails: investigate, fix, rerun.
442
443**Key reminders**:
444- HTTP 200 = element found, NOT test completed
445- If no test actions in logs = FALSE SUCCESS
446- If Appium can't find initial element = app crashed or AutomationIds wrong
447
448---
449
450### 📝 Note for User
451
452**Test scenario is ready in Sandbox for manual verification.**
453
454**To verify bug reproduction (optional):**
455```bash
456# 1. Revert the PR fix files
457git checkout main -- [list specific fix files from PR]
458
459# 2. Rerun test - bug should appear
460pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
461
462# 3. Restore fix
463git checkout HEAD -- [fix files]
464
465# 4. Rerun test - bug should be gone
466pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
467```
468
469This proves the test scenario correctly reproduces the bug.
470
471---
472
473## 🔄 Iterative Testing Workflow (MANDATORY PROCESS)
474
475**🚨 CRITICAL**: This is THE workflow for Sandbox testing. Do NOT use manual `adb`/`xcrun` commands to bypass it.
476
477### The Required Loop
478
479```
480┌─────────────────────────────────────────────────────────────┐
481│ 1. Update MainPage.xaml[.cs] with your test scenario │
482│ - Add UI elements for reproduction │
483│ - Add AutomationIds to all interactive elements │
484│ - Add Console.WriteLine markers for debugging │
485├─────────────────────────────────────────────────────────────┤
486│ 2. Update Appium test to match your MainPage │
487│ CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs │
488│ - Update element locators to match AutomationIds │
489│ - Add test logic (tap buttons, verify labels) │
490├─────────────────────────────────────────────────────────────┤
491│ 3. Run BuildAndRunSandbox.ps1 │
492│ pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform X │
493├─────────────────────────────────────────────────────────────┤
494│ 4. Validate results using SYSTEMATIC CHECKLIST │
495│ - Step 1: Check for errors/exceptions │
496│ - Step 2: Verify test actions (Tapping, etc.) │
497│ - Step 3: Verify "Test completed" │
498│ - Step 4: Check device logs for SANDBOX markers │
499│ - Step 5-6: Screenshots and exit code │
500├─────────────────────────────────────────────────────────────┤
501│ 5. Did ALL validation checks pass? │
502│ YES → Report success with summary (go to step 8) │
503│ NO → Continue to step 6 │
504├─────────────────────────────────────────────────────────────┤
505│ 6. Investigate failure from captured logs │
506│ - Read CustomAgentLogsTmp/Sandbox/android-device.log │
507│ - Read CustomAgentLogsTmp/Sandbox/build-run-output.log │
508│ - Identify root cause (element not found? crash?) │
509├─────────────────────────────────────────────────────────────┤
510│ 7. Fix the issue and LOOP BACK TO STEP 3 │
511│ - Update MainPage if UI/code issue │
512│ - Update RunWithAppiumTest.cs if test issue │
513│ - Update both if AutomationId mismatch │
514│ - Max 3 iterations before reporting as blocked │
515├─────────────────────────────────────────────────────────────┤
516│ 8. Report comprehensive summary to user │
517│ - Test scenario source and justification │
518│ - Validation results │
519│ - Verdict (success/partial/issues/blocked) │
520└─────────────────────────────────────────────────────────────┘
521```
522
523### ❌ What NOT To Do
524
525**Never use manual commands during testing**:
526- ❌ `adb logcat`, `adb shell`, `adb install`
527- ❌ `xcrun simctl spawn`, `xcrun simctl install`
528- ❌ `dotnet build`, `dotnet run`
529
530**Why**: Script already captured everything. Manual commands show CURRENT state, not test execution state.
531
532**✅ Correct**: Edit files → Rerun `BuildAndRunSandbox.ps1`
533
534### ✅ Correct Iteration Example
535
536**Most common case - Test fails to find element**:
537```bash
538# 1. Check what went wrong
539grep "no such element" CustomAgentLogsTmp/Sandbox/build-run-output.log
540
541# 2. Check what DOES exist in MainPage
542grep AutomationId src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml
543
544# 3. Fix MainPage: Add AutomationIds
545# Edit MainPage.xaml: <Button AutomationId="NavigateButton" ...
546
547# 4. Fix test: Update to match
548# Edit RunWithAppiumTest.cs: App.WaitForElement("NavigateButton");
549
550# 5. Rerun
551pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform android
552```
553
554**When validation passes**: Report success with comprehensive summary
555
556### When to Stop Iterating
557
558- ✅ **All validation checks pass** → Report success with detailed summary
559- ❌ **Max 3 iterations reached** → **STOP and report**: "I wasn't able to reproduce the issue. What should I try next?"
560- ❌ **Build fails repeatedly** → **STOP and report**: "I wasn't able to reproduce the issue due to build failures. What should I try next?"
561- ❌ **Root cause unclear after log analysis** → **STOP and report**: "I wasn't able to reproduce the issue. What should I try next?"
562- ❌ **Issue appears to be PR bug, not test** → **STOP and report findings to user**: "I wasn't able to reproduce the issue - it appears there may be an issue with [details]. What should I try next?"
563- ❌ **Cannot reproduce the issue** → **STOP immediately**: "I wasn't able to reproduce the issue. What should I try next?"
564
565**CRITICAL**: When you cannot reproduce or hit blockers, **PAUSE and ask the user**. Do NOT:
566- ❌ Switch to a different branch (e.g., `git checkout main`)
567- ❌ Try alternative approaches without asking first
568- ❌ Change the workflow significantly without user guidance
569
570### Mental Model: The Script is Your Robot
571
572BuildAndRunSandbox.ps1 handles: build → deploy → capture logs → run test → report
573
574**Your workflow**: Edit files → Run script → Read logs → Fix issues → Repeat
575
576---
577
578## Output Format
579
580Provide a concise test summary:
581
582```markdown
583## PR Testing Summary
584
585**PR**: #XXXXX - [Title]
586**Platform Tested**: Android/iOS
587**Issue**: [Brief description]
588
589---
590
591### Test Scenario Setup
592
593**🚨 REQUIRED - Source of Test Scenario**:
594- **Source**: [From issue reproduction / From PR UITest / Custom scenario]
595- **Why this source**: [e.g., "Issue #XXXXX provides detailed repro steps" / "PR includes UITest that demonstrates the fix" / "No repro available, created scenario based on PR code changes"]
596- **Link to source**: [URL to issue comment with repro, or path to UITest file]
597
598**What was tested**:
599- [Specific actions taken - e.g., "Tap 'Toggle RTL' button, then tap 'Show Dialog' button"]
600- [UI elements involved - e.g., "Button with AutomationId='ToggleButton', Dialog with Label"]
601- [Expected behavior - e.g., "Dialog should appear with correct RTL padding on label"]
602
603---
604
605### Test Results WITH PR Fix
606
607**Observed Behavior**:
608- [What happened when running the test]
609- [Appium test results]
610- [Relevant log excerpts]
611
612**Screenshots**: [Reference if taken, but not for validation]
613
614---
615
616### Verdict
617
618✅ **FIX VALIDATED** - Test scenario completes successfully, expected behavior observed
619OR
620⚠️ **PARTIAL** - Fix appears to work but [note any concerns]
621OR
622❌ **ISSUES FOUND** - [Specific problems encountered]
623OR
624🚫 **CANNOT TEST** - [Build failures, setup issues, etc.]
625
626---
627
628### Notes for User
629- Test scenario is set up in Sandbox and ready for manual verification if needed
630- To verify bug reproduction without fix, revert PR changes: `git checkout main -- [fix files]`
631- Then rerun: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]`
632```
633
634---
635
636## Best Practices
637
6381. **Use issue reproduction when available** - Most reliable test scenario
6392. **Adapt PR's UITests if no repro** - They're already designed to test the fix
6403. **Validate programmatically, reference visually** - Use Appium element queries for validation, screenshots only for additional context
6414. **Use colored backgrounds** - Makes layout issues visible
6425. **Add console markers** - Easy to grep logs
6436. **Test multiple iterations** - Race conditions need multiple runs (3-5 times)
6447. **Leave Sandbox as-is** - User will iterate on it after your testing
6458. **Document your test scenario thoroughly** - Include source (issue/UITest/custom), why you chose it, specific actions, and expected behavior so user can verify
646
647**Screenshot Usage**:
648- ✅ Take screenshots for **context and reference** (e.g., showing layout before/after)
649- ✅ Include in report if they provide **additional insight** beyond what logs show
650- ❌ Do NOT rely on screenshots as **primary validation** - use Appium element queries and log analysis
651- ❌ Do NOT take screenshots just to show "it works" - validation should come from test assertions
652
653---
654
655## Log Capture and Review
656
657### Where Logs Are Saved
658
659After running BuildAndRunSandbox.ps1, all logs are in `CustomAgentLogsTmp/Sandbox/`:
660
6611. **Android**: `CustomAgentLogsTmp/Sandbox/android-device.log`
6622. **iOS**: `CustomAgentLogsTmp/Sandbox/ios-device.log`
6633. **Appium**: `CustomAgentLogsTmp/Sandbox/appium.log`
664
665### Viewing Logs
666
667```bash
668# View device logs
669cat CustomAgentLogsTmp/Sandbox/android-device.log
670# or
671cat CustomAgentLogsTmp/Sandbox/ios-device.log
672
673# Search for specific output
674grep "TEST OUTPUT" CustomAgentLogsTmp/Sandbox/android-device.log
675
676# View Appium logs
677cat CustomAgentLogsTmp/Sandbox/appium.log
678```
679
680### 📝 Adding Debug Logging to Your Test Scenario
681
682**Use `Console.WriteLine` for logging** - it works on all platforms.
683
684```csharp
685// Use a unique prefix for easy grep
686Console.WriteLine("SANDBOX: Button clicked");
687Console.WriteLine($"SANDBOX: Value is {myValue}");
688```
689
690**Searching logs:**
691```bash
692grep "SANDBOX" CustomAgentLogsTmp/Sandbox/android-device.log
693grep "SANDBOX" CustomAgentLogsTmp/Sandbox/ios-device.log
694grep "SANDBOX" CustomAgentLogsTmp/Sandbox/catalyst-device.log
695```
696
697---
698
699## 🚨 ABSOLUTE RULE: BuildAndRunSandbox.ps1 is THE ONLY Deployment Method
700
701**THIS IS MANDATORY. NOT A SUGGESTION.**
702
703❌ If typing `adb`/`xcrun` commands during testing → STOP. You're violating the workflow.
704
705**Why**: Manual commands show CURRENT state, not test execution state. Script already captured correct logs during test.
706
707**❌ NEVER during testing**: `adb logcat`, `adb install`, `adb shell`, `xcrun simctl install/spawn`, `dotnet build/run`
708
709**✅ ONLY exception**: Finding/booting specific iOS device BEFORE running script (`xcrun simctl list/boot`)
710
711**Correct workflow**:
7121. Edit files (MainPage, RunWithAppiumTest.cs)
7132. Run: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform X`
7143. Analyze logs in `CustomAgentLogsTmp/Sandbox/` (android-device.log, appium.log)
7154. Fix issues, rerun script
716
717**Expected logs**: `android-device.log` or `ios-device.log`, `appium.log`, `RunWithAppiumTest.cs`, optional screenshots
718
719---
720
721## Troubleshooting & Recovery
722
723**Retry up to 3 times before reporting as blocked.** After each failure: analyze logs → fix → rerun script.
724
725### Common Issues
726
727| Issue | Recovery | Max Retries |
728|-------|----------|-------------|
729| Build error | Check SDK version, `dotnet tool restore` | 2 |
730| App crash | Check stack trace in device log, fix code/XAML | 3 |
731| Element not found | Verify AutomationIds match, check app loaded | 2 |
732| Fast Deployment (Android) | Add `appium:noReset` capability | 1 |
733| XAML parse error | Verify event handler exists in code-behind | 2 |
734
735### Element Not Found Debugging
736
737🚨 If Appium can't find initial element, app is NOT running correctly.
738
739**Check**:
740```bash
741# Look for crashes
742grep -i "FATAL\|crash\|exception" CustomAgentLogsTmp/Sandbox/android-device.log | tail -20
743
744# Verify app launched
745grep "SANDBOX.*MainPage" CustomAgentLogsTmp/Sandbox/android-device.log
746```
747
748**Root causes**: App crashed, XAML parse error, AutomationId mismatch, Android Fast Deployment
749
750### When to Stop & Report
751- ✅ **Continue**: Minor warnings, non-critical timeouts, platform differences
752- ❌ **Stop and ask user**: Can't checkout PR, build fails after max retries, SDK mismatch, root cause unclear, cannot reproduce issue
753
754**When blocked, ALWAYS report to user with this format**:
755```markdown
756I wasn't able to reproduce the issue. Here's what I tried:
757
7581. [What I attempted]
7592. [Issues encountered]
7603. [Current state of reproduction attempt]
761
762What should I try next?
763```
764
765**DO NOT** try alternative approaches without asking first. **DO NOT** switch branches.
766
767### Test Shows Unexpected Behavior
768**Action**: Document and report
769
770```markdown
771⚠️ Unexpected behavior during testing
772
773**What I expected**: [Based on issue description]
774
775**What I observed**: [Actual behavior]
776
777**Test scenario**: [What was tested]
778
779**Logs**: [Relevant excerpts]
780
781**Question for user**: Is this expected behavior, or does this indicate an issue?
782```
783
784---
785
786## Common Mistakes to Avoid
787
788- ❌ Using TestCases.HostApp for manual PR validation (use Sandbox)
789- ❌ Manual build/deploy commands instead of BuildAndRunSandbox.ps1
790- ❌ Testing only one platform when PR affects multiple
791- ❌ Using screenshots for validation (use Appium element queries)
792- ❌ Creating test scenario without checking issue for reproduction steps
793- ❌ Ignoring PR's existing UITests when available
794- ❌ Cleaning up or reverting Sandbox changes (user will iterate on it)
795
796**Testing Tips**:
797- For layout bugs: Use `element.GetRect()` to measure positions
798- For SafeArea PRs: Measure child content position, not parent size
799- Add `Console.WriteLine("SANDBOX: ...")` markers for debugging
800
801---
802
803## Appendix: Cleanup (Only When User Requests)
804
805⚠️ **DO NOT clean up after testing** - Leave Sandbox as-is so user can iterate on it.
806
807Only use these commands if the **user explicitly requests cleanup**:
808
809### Sandbox App Cleanup (User Request Only)
810```bash
811# Revert all changes to Sandbox app
812git checkout -- src/Controls/samples/Controls.Sample.Sandbox/
813```
814
815### Sandbox Test Files Cleanup (User Request Only)
816```bash
817# Remove Appium test directory (gitignored)
818rm -rf CustomAgentLogsTmp/Sandbox/
819```
820
@@ −1 +1 @@
11 ---
2−description: "Guidance for GitHub Copilot when working on the .NET MAUI repository."
2+description: "Comprehensive guide for working with the .NET MAUI Sandbox app for testing, validation, and experimentation"
3+applyTo: "src/Controls/samples/Controls.Sample.Sandbox/**"
34 ---
45
5−# GitHub Copilot Development Environment Instructions
6+# Sandbox Testing Guide
67
7−This document provides specific guidance for GitHub Copilot when working on the .NET MAUI repository. It serves as context for understanding the project structure, development workflow, and best practices.
8+Comprehensive guide for working with the .NET MAUI Sandbox app for manual testing, PR validation, issue reproduction, and experimentation with MAUI features.
89
9−## Code Review Instructions
10+## When This Applies
1011
11−When performing a code review on PRs that change functional code, run the pr-finalize skill to verify that the PR title and description accurately match the actual implementation. This ensures proper documentation and helps maintain high-quality commit messages.
12+This guide applies when you:
13+- Work with files in `src/Controls/samples/Controls.Sample.Sandbox/`
14+- User asks to "test this PR" or "validate PR #XXXXX" in Sandbox
15+- User asks to "reproduce issue #XXXXX" in Sandbox
16+- User wants to deploy to iOS/Android for manual testing
17+- User mentions Sandbox app by name in testing context
1218
13−## Repository Overview
19+## 🚨 CRITICAL VALIDATION RULES - READ FIRST
1420
15−**.NET MAUI** is a cross-platform framework for creating mobile and desktop applications with C# and XAML. This repository contains the core framework code that enables development for Android, iOS, iPadOS, macOS, and Windows from a single shared codebase.
21+**YOU MUST FOLLOW THESE RULES WHEN RUNNING SANDBOX TESTS:**
1622
17−### Key Technologies
23+### What You NEVER Do (Absolute Rules)
1824
19−- **.NET SDK** - Version is **ALWAYS** defined in `global.json` at repository root
20− - **main branch**: Latest stable .NET version
21− - **Feature branches**: Each `netN.0` branch targets the .NET N SDK. By convention, the highest `netN.0` branch is the current development branch for new features and API changes.
22−- **Cake build system** for compilation and packaging (`dotnet cake`)
23−- **MSBuild** with custom build tasks (must build `Microsoft.Maui.BuildTasks.slnf` first)
24−- **Testing frameworks**:
25− - **xUnit** - Unit tests (`*.UnitTests.csproj`)
26− - **NUnit** - UI tests (`TestCases.Shared.Tests`)
27− - **Appium WebDriver** - UI test automation
25+- ❌ **NEVER** assume test completion without validation
26+- ❌ **NEVER** claim success based on HTTP 200 responses alone (element found ≠ test completed)
27+- ❌ **NEVER** skip the mandatory validation checklist
28+- ❌ **NEVER** proceed without verifying device logs show expected behavior
29+- ❌ **NEVER** assume Appium connection means test finished
30+- ❌ **NEVER** claim button was tapped without checking device logs
31+- ❌ **NEVER** switch branches (e.g., `git checkout main`) during reproduction - stay on current branch
2832
29−## Development Environment Setup
33+### What You ALWAYS Do (Mandatory Steps)
3034
31−This guidance assumes:
32−- Repository is already cloned and tools are restored (`dotnet tool restore` completed)
33−- Build tasks are compiled (`Microsoft.Maui.BuildTasks.slnf` built successfully)
34−- Correct .NET SDK version installed (verify with `dotnet --version` against `global.json`)
35+- ✅ **ALWAYS** save full output to file for analysis
36+- ✅ **ALWAYS** check for errors/exceptions FIRST before claiming success
37+- ✅ **ALWAYS** verify "Test completed" marker appears in output
38+- ✅ **ALWAYS** verify expected test actions in logs (Tapping, Screenshot, etc.)
39+- ✅ **ALWAYS** check device logs for Console.WriteLine markers (e.g., "SANDBOX: ...")
40+- ✅ **ALWAYS** verify artifacts exist (screenshots, if test captures them)
3541
36−### Platform-Specific Requirements
42+### Rule 1: NEVER ASSUME TEST COMPLETION
43+- ❌ **DO NOT** assume the test completed successfully just because Appium connected
44+- ❌ **DO NOT** assume success based on HTTP 200 responses (element found ≠ test completed)
45+- ✅ **DO** verify test completion by checking for completion markers in output
46+- ✅ **DO** search for "Test completed", "═══════", or final summary messages
3747
38−- **Android**: OpenJDK 17 + Android SDK (install via `android` command after `dotnet tool restore`)
39−- **iOS/macOS**: Xcode (current stable version)
40−- **Windows**: Windows SDK
48+### Rule 2: ALWAYS VALIDATE TEST OUTPUT
49+After running BuildAndRunSandbox.ps1, you MUST:
50+1. **Save full output to file**: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios > CustomAgentLogsTmp/Sandbox/build-run-output.log 2>&1`
51+2. **Check for errors FIRST**: `grep -E "ERROR|Exception|failed" CustomAgentLogsTmp/Sandbox/build-run-output.log`
52+3. **Verify completion markers**: `grep "Test completed\|══════" CustomAgentLogsTmp/Sandbox/build-run-output.log`
53+4. **Check for expected actions**: `grep "Tapping\|Screenshot saved\|switched to" CustomAgentLogsTmp/Sandbox/build-run-output.log`
4154
42−## Project Structure
55+### Rule 3: VALIDATE DEVICE LOGS FOR EXPECTED BEHAVIOR
56+- ✅ **DO** check device logs confirm your expected test actions happened
57+- ✅ **DO** grep for your Console.WriteLine markers (e.g., "SANDBOX.*CLICKED")
58+- ❌ **DO NOT** claim the test worked without verifying device logs show the action
4359
44−### Important Directories
45−- `src/Core/` - Core MAUI framework code
46−- `src/Controls/` - UI controls and components
47−- `src/Essentials/` - Platform APIs and essentials
48−- `src/TestUtils/` - Testing utilities and infrastructure
49−- `docs/` - Development documentation
50−- `eng/` - Build engineering and tooling
51−- `.github/` - GitHub workflows and configuration
60+### Rule 4: SYSTEMATIC VALIDATION CHECKLIST
61+After EVERY test run, verify ALL of these **IN THIS ORDER**:
5262
53−### Platform-Specific Code Organization
54−- **Android** specific code is inside folders labeled `Android`
55−- **iOS** specific code is inside folders labeled `iOS`
56−- **MacCatalyst** specific code is inside folders named `MacCatalyst`
57−- **Windows** specific code is inside folders named `Windows`
63+```bash
64+# Step 1: Check for errors/exceptions FIRST
65+grep -iE "error|exception|failed" CustomAgentLogsTmp/Sandbox/build-run-output.log | grep -v "no such element" | head -20
5866
59−### Platform-Specific File Extensions
67+# Step 2: Verify expected test actions (MOST IMPORTANT - proves test actually ran)
68+grep -E "Tapping|Screenshot saved|Found.*element|Clicking|Entering text" CustomAgentLogsTmp/Sandbox/build-run-output.log
6069
61−Platform-specific files use naming conventions to control compilation:
70+# Step 3: Verify test completion marker
71+grep "Test completed" CustomAgentLogsTmp/Sandbox/build-run-output.log
6272
63−**File extension patterns**:
64−- `.windows.cs` - Windows TFM only
65−- `.android.cs` - Android TFM only
66−- `.ios.cs` - iOS and MacCatalyst TFMs (both)
67−- `.maccatalyst.cs` - MacCatalyst TFM only (does NOT compile for iOS)
73+# Step 4: Verify device logs show expected behavior
74+grep "SANDBOX" CustomAgentLogsTmp/Sandbox/android-device.log # or ios-device.log
6875
69−**Important**: Both `.ios.cs` and `.maccatalyst.cs` files compile for MacCatalyst. There is no precedence mechanism that excludes one when the other exists.
76+# Step 5: Check screenshots were saved (if test captures them)
77+ls -lh CustomAgentLogsTmp/Sandbox/*.png
7078
71−**Example**: If you have both `CollectionView.ios.cs` and `CollectionView.maccatalyst.cs`, both will compile for MacCatalyst builds. The `.maccatalyst.cs` file won't compile for iOS, but the `.ios.cs` file will compile for both iOS and MacCatalyst.
79+# Step 6: Check exit code
80+echo $? # Should be 0 for success
81+```
7282
73−### Sample Projects
83+**CRITICAL**: If Step 2 shows NO test actions, the test didn't actually run even if it "completed successfully". Update your Appium test and rerun.
7484
75−- `src/Controls/samples/Maui.Controls.Sample` - Full gallery sample with all controls and features
76−- `src/Controls/samples/Maui.Controls.Sample.Sandbox` - Empty project for testing/reproduction
77−- `src/Essentials/samples/Essentials.Sample` - Essentials API demonstrations (non-UI MAUI APIs)
78−- `src/BlazorWebView/samples/` - BlazorWebView sample applications
85+**If ANY of these checks fail, the test DID NOT complete successfully. Investigate and fix before proceeding.**
7986
80−## Development Workflow
87+---
8188
82−### Testing
89+## 🚨 WARNING: "Test Completed Successfully" ≠ Test Actually Worked
8390
84−Major test projects:
85−- **Core**: `src/Core/tests/UnitTests/Core.UnitTests.csproj`
86−- **Essentials**: `src/Essentials/test/UnitTests/Essentials.UnitTests.csproj`
87−- **Controls**: `src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj`
88−- **XAML**: `src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj`
91+**CRITICAL UNDERSTANDING**: The message "✅ Test completed successfully" only means:
92+- ✅ Appium test script finished running without crashing
93+- ✅ Script exit code was 0
8994
90−Find all tests: `find . -name "*.UnitTests.csproj"`
95+**It does NOT mean**:
96+- ❌ Appium found your UI elements
97+- ❌ Buttons were clicked
98+- ❌ Navigation happened
99+- ❌ Your test scenario actually ran
91100
92−### CI Pipelines (Azure DevOps)
101+### Example of False Success
93102
94−When referencing or triggering CI pipelines, use these current pipeline names:
103+**What you see in output**:
104+```
105+✅ Test completed successfully
95106
96−| Pipeline | Name | Purpose |
97−|----------|------|---------|
98−| Overall CI | `maui-pr` | Full PR validation build |
99−| Device Tests | `maui-pr-devicetests` | Helix-based device tests |
100−| UI Tests | `maui-pr-uitests` | Appium-based UI tests |
107+╔═══════════════════════════════════════════════════════════╗
108+║ Test Summary ║
109+╠═══════════════════════════════════════════════════════════╣
110+║ Platform: ANDROID ║
111+║ Device: emulator-5554 ║
112+║ Result: SUCCESS ✅ ║
113+╚═══════════════════════════════════════════════════════════╝
114+```
101115
102−**⚠️ Old pipeline names** (e.g., `MAUI-UITests-public`, `MAUI-public`) are **outdated** and should NOT be used. Always use the names above.
116+**What actually happened**:
117+```bash
118+# Check the logs:
119+grep "no such element" CustomAgentLogsTmp/Sandbox/build-run-output.log
120+# Result: 20+ lines of "no such element" errors
103121
104−### Investigating CI Failures
122+# The test looked for "InstructionLabel" which doesn't exist in MainPage
123+# Appium never found ANY elements
124+# Test script just gave up and exited with code 0
125+# NO ACTUAL TESTING WAS PERFORMED
126+```
105127
106−**🚨 ALWAYS use the `azdo-build-investigator` skill when investigating CI failures or assessing merge readiness.** Its instructions direct you to invoke the `ci-analysis` skill first for the core investigation workflow, then apply MAUI-specific corrections (correct pipeline names, XHarness quirks, binlog guidance).
128+### How to Detect False Success
107129
108−Do NOT default to manually querying AzDO APIs or rely solely on `gh pr checks` pass/fail counts.
130+**MANDATORY check after EVERY "successful" test**:
131+```bash
132+# Look for actual test actions in output
133+grep -E "Tapping|Clicking|Found element|Screenshot saved" CustomAgentLogsTmp/Sandbox/build-run-output.log
134+```
109135
110−**When to use it:**
111−- "How does CI look?" / "Is CI green?" / "Can we merge?"
112−- "What's failing?" / "Are these known failures?"
113−- "Is this PR safe to merge?" / "Any CI concerns?"
114−- After any PR push to verify the build
136+**If grep returns NOTHING → FALSE SUCCESS**:
137+- Test didn't actually do anything
138+- Template test is looking for elements that don't exist
139+- You MUST update `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` to match your MainPage
140+- Rerun BuildAndRunSandbox.ps1 after updating test
115141
116−**Verifying specific tests:** When asked "did test X pass?" or "did the new test run?", query the **actual AzDO test results** — do NOT infer whether a test ran by inspecting code attributes. Class-level traits, base class categories, and assembly-level attributes can all cause a test to run even when the method itself has no visible category. Check the evidence, not the code.
142+**If grep returns multiple lines → REAL SUCCESS**:
143+- Test found elements and interacted with them
144+- Proceed with full validation checklist
117145
118−**Anti-pattern:** Writing ad-hoc scripts to parse AzDO build timelines. The skills handle Helix work item details, known issue cross-referencing, and test result aggregation that manual approaches miss.
146+---
119147
120−### Gradle / Maven Dependency Failures (CFSClean)
148+## Purpose
121149
122−The official CI build uses CFSClean network isolation which blocks `repo.maven.apache.org`. All Gradle/Maven dependencies resolve through the `dotnet-public-maven` Azure Artifacts feed.
150+Work with the Sandbox app for manual testing, PR validation, issue reproduction, and experimentation with MAUI features.
123151
124−**If CI fails with Gradle 401 errors** like `"No local versions of package"` or `"Please provide authentication to save package from upstream"`, it means a Maven package hasn't been ingested into the feed yet. **Fix:** run `./eng/ingest-maven-deps.sh` locally to pre-populate the feed. See `src/Core/AndroidNative/settings.gradle` for details.
152+## When to Use Sandbox Testing
125153
126−**Do NOT upgrade Gradle past 8.x** — the Android SDK's `net.android.init.gradle.kts` is incompatible with Gradle 9.x (`dotnet/android#10738`).
154+- ✅ User asks to "test this PR" (functional testing, not code review)
155+- ✅ User asks to "validate PR #XXXXX" or "validate PR #XXXXX in Sandbox"
156+- ✅ User asks to "reproduce issue #XXXXX" or "try out issue #XXXXX"
157+- ✅ User asks to "try out" or "experiment with" a feature in Sandbox
158+- ✅ PR modifies core MAUI functionality (controls, layouts, platform code)
159+- ✅ Need to manually verify a fix works on device/simulator
160+- ✅ Need to create a quick test scenario for hands-on validation
127161
128−### Code Formatting
162+## When NOT to Use Sandbox
129163
130−Always format code before committing:
164+- ❌ User asks to "review PR #XXXXX" → Use **pr** agent for code review
165+- ❌ User asks to "write tests" or "create automated tests" → Use **write-tests-agent**
166+- ❌ User asks to "validate the UI tests" or "verify test quality" → Review test code instead
167+- ❌ User asks to "fix issue #XXXXX" (no PR exists) → Suggest `/delegate` command
168+- ❌ PR only adds documentation (no code changes to test)
169+- ❌ PR only modifies build scripts (no functional changes)
131170
171+## Distinction: Code Review vs. Functional Testing
172+
173+**Code Review** (pr-review skill):
174+- Analyzes code quality, patterns, best practices
175+- Reviews test coverage and correctness
176+- Checks for potential bugs or issues in the code itself
177+- Trigger: "review PR", "work on PR"
178+
179+**Functional Testing** (sandbox-agent):
180+- Builds and deploys PR to device/simulator
181+- Manually validates the fix works as expected
182+- Reproduces issues and verifies they're resolved
183+- Trigger: "test this PR", "validate PR in Sandbox", "reproduce issue"
184+
185+## 🚨 Critical Requirements for Android Testing
186+
187+**ANDROID-ONLY REQUIREMENT - appium:noReset**
188+
189+⚠️ **This ONLY applies to Android, NOT iOS**
190+
191+When testing on Android, the Appium test script **MUST** have this capability:
192+
193+```csharp
194+// ANDROID ONLY - Do NOT add this for iOS
195+if (PLATFORM == "android")
196+{
197+ options.AddAdditionalAppiumOption("appium:noReset", true);
198+}
199+```
200+
201+**Why this is critical for Android:**
202+- Without `noReset`, Appium clears app data between runs
203+- This breaks .NET MAUI's Fast Deployment mechanism on Android
204+- App crashes with: `"No assemblies found in '.../__override__/...' ... Assuming this is part of Fast Deployment. Exiting..."`
205+- The app will crash immediately on launch before any test can run
206+
207+**iOS does NOT need this** - iOS deployment works differently and doesn't use Fast Deployment
208+
209+**Where to set it:**
210+- Template: `.github/scripts/templates/RunWithAppiumTest.template.cs` (line ~68, Android section only)
211+- Active test: `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` (Android section only)
212+
213+**Platform detection is automatic** - The template automatically detects Android vs iOS from the UDID format, so you don't need to manually set the platform. The `if (PLATFORM == "android")` block will execute automatically when testing on Android.
214+
215+**⚠️ NEVER REMOVE THIS CAPABILITY FROM ANDROID** - All Android tests depend on it
216+
217+---
218+
219+## Core Workflow
220+
221+**🚨 CRITICAL RULES FOR ENTIRE WORKFLOW:**
222+- **ALWAYS use BuildAndRunSandbox.ps1 script** for building, deploying, and testing
223+- **NEVER use manual `dotnet build`, `adb`, or `xcrun` commands**
224+- **NEVER switch branches during reproduction** - stay on the current branch
225+- **ALWAYS stop and ask user if you cannot reproduce** - do not try alternative branches
226+- The script handles device detection, build, deployment, and test execution automatically
227+- See "BuildAndRunSandbox.ps1 Script" section below for full details
228+
229+---
230+
231+### Step 1: Understand Issue (DO NOT Checkout PR Unless Instructed)
232+
233+**⚠️ IMPORTANT**: Only checkout a PR if the user explicitly asks you to test a specific PR. For general issue reproduction, work on the current branch.
234+
132235 ```bash
133−dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822
236+# ONLY if user explicitly asks to test a PR:
237+gh pr checkout <PR_NUMBER>
134238 ```
135239
136−## Contribution Guidelines
240+**Understand the issue thoroughly:**
241+- Read issue report or PR description
242+- Identify what bug needs to be reproduced
243+- Note affected platforms
244+- Look for reproduction steps in the issue
245+- If testing a PR: Review PR changes to understand the fix
137246
138−### Handling Existing PRs for Assigned Issues
247+---
139248
140−**🚨 CRITICAL REQUIREMENT: Always develop your own solution first, then compare with existing PRs.**
249+### Step 2: Create Test Scenario in Sandbox
141250
142−1. **Develop your own solution first** - Analyze the issue independently and design your approach without looking at existing PRs
143−2. **Search for existing PRs** - After developing your solution, search for open PRs addressing the same issue
144−3. **Compare and evaluate** - Examine existing PR approaches and decide which solution better addresses the issue
145−4. **Document your decision** - In your PR description, compare your solution to existing PRs and explain why you chose your approach, including concerns with alternatives
146−5. **Improve either solution** - Whether using your solution or an existing one, enhance with better tests, code quality, error handling, or documentation
251+**Choose test scenario source (in priority order):**
147252
148−### Auto-Generated Files (Never Commit)
253+1. **From Issue Reproduction** (Preferred)
254+ - Look for "Reproduction" or "Steps to Reproduce" in the linked issue
255+ - Use the exact scenario the user reported
256+ - This proves you're testing what the user experienced
149257
150−These files are auto-generated and must NOT be committed:
151−- `cgmanifest.json` - Generated during CI builds
152−- `templatestrings.json` - Auto-generated localization
258+2. **From PR's UI Tests** (Alternative)
259+ - Check if PR includes files in `TestCases.HostApp/Issues/IssueXXXXX.*`
260+ - Adapt the test page code to Sandbox
261+ - Simplify if needed for manual testing
153262
154−**For AI agents:** Always reset changes to these files before committing.
263+3. **Create Your Own** (Last Resort)
264+ - If no repro available, design scenario based on PR changes
265+ - Focus on the specific code paths modified by the fix
266+ - Keep it simple and focused
155267
156−### PublicAPI.Unshipped.txt File Management
268+**Files to modify**:
269+- `src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml[.cs]` - UI and code for reproduction
270+- `CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs` - Appium test script (MANDATORY - see setup below)
157271
158−When working with public API changes:
159−- **Never disable analyzers** to bypass PublicAPI.Unshipped.txt issues
160−- **Always add correct API entries** to PublicAPI.Unshipped.txt files
161−- **Use `dotnet format analyzers`** if having trouble
162−- **If files are incorrect**: Revert all changes, then add only the necessary new API entries
272+**Setting up the Appium test file (MANDATORY):**
163273
164−### Branching
165−- `main` - For bug fixes without API changes
166−- The highest `netN.0` branch (by convention) - For new features and API changes. To find it, run `git fetch origin` then: `git for-each-ref --sort=-version:refname --count=1 --format='%(refname:lstrip=3)' refs/remotes/origin/net*.0`
274+🚨 **CRITICAL**: Update Appium test BEFORE running script. Template will give FALSE SUCCESS otherwise.
167275
168−### Git Workflow (Copilot CLI Rules)
276+1. **Create test file**:
277+ ```bash
278+ mkdir -p CustomAgentLogsTmp/Sandbox
279+ cp .github/scripts/templates/RunWithAppiumTest.template.cs CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs
280+ ```
169281
170−**🚨 CRITICAL Git Rules for Copilot CLI:**
282+2. **Update test to match MainPage**:
283+ - Check AutomationIds: `grep AutomationId MainPage.xaml`
284+ - Update test to use those IDs (not template defaults)
285+ - Add test logic: tap buttons, verify labels
286+ - Add Console.WriteLine markers for debugging
171287
172−1. **NEVER commit directly to `main`** - Always create a feature branch for your work. Direct commits to `main` are strictly prohibited.
288+3. **Example**:
289+ ```bash
290+ # Check MainPage
291+ grep 'AutomationId=' MainPage.xaml
292+ # Update test: App.WaitForElement("NavigateButton");
293+ ```
173294
174−2. **When amending an existing PR, work on the PR's branch directly** - Do NOT create a separate branch off a PR branch. The PR branch already IS a feature branch. Creating a new branch off it means CI won't run on the original PR, defeating the purpose. Use `gh pr checkout` to switch to the PR branch, make your changes, commit, **then** ask before pushing so the user can review locally first.
295+**Checklist**:
296+- ✅ Add AutomationIds to MainPage.xaml elements
297+- ✅ Update RunWithAppiumTest.cs to match
298+- ✅ Add SANDBOX markers for debugging
175299
176−3. **Do NOT rebase, squash, or force-push** unless explicitly requested by the user. These operations rewrite git history and can cause problems for other contributors. Default behavior should be regular commits and pushes.
300+**🚨 CRITICAL - Document Your Test Scenario:**
177301
178−**Safe Git Workflow:**
302+You MUST include in your final report:
303+- ✅ **Source**: Where did the test scenario come from? (issue reproduction / PR UITest / custom)
304+- ✅ **Why**: Why did you choose that source? (e.g., "Issue #XXXXX provides detailed repro steps")
305+- ✅ **What**: What specific actions does your test perform? (e.g., "Tap button → verify label changes to 'Success'")
306+- ✅ **Expected**: What behavior should occur? (from issue description or PR changes)
307+
308+Without this documentation, user cannot verify you tested the right thing.
309+
310+---
311+
312+### Step 3: Test WITH PR Fix
313+
314+**Platform Selection Decision Tree:**
315+
316+Follow this flowchart in order - stop at the first match:
317+
318+```
319+┌─────────────────────────────────────────────────────────────────┐
320+│ 1. Does PR title have platform tag? [Android], [iOS], etc. │
321+│ YES → Test that platform ONLY │
322+│ NO → Continue to step 2 │
323+├─────────────────────────────────────────────────────────────────┤
324+│ 2. Are ALL modified files in platform-specific paths? │
325+│ (Platform/Android/, Platform/iOS/, *.Android.cs, etc.) │
326+│ YES → Test that platform ONLY │
327+│ NO → Continue to step 3 │
328+├─────────────────────────────────────────────────────────────────┤
329+│ 3. Does issue report mention a specific platform? │
330+│ YES (one platform) → Test that platform ONLY │
331+│ YES (multiple) → Test Android + iOS │
332+│ NO → Continue to step 4 │
333+├─────────────────────────────────────────────────────────────────┤
334+│ 4. Is this high-risk cross-platform code? │
335+│ (Controls/, Core/, layout, navigation, critical controls) │
336+│ YES → Test Android + iOS │
337+│ NO → Test Android ONLY (default - faster) │
338+└─────────────────────────────────────────────────────────────────┘
339+```
340+
341+**Platform-specific path indicators:**
342+- `Platform/Android/` or `Platform/iOS/` → Platform-specific
343+- Files with `.Android.`, `.iOS.`, `.MacCatalyst.` in name → Platform-specific
344+- `Controls/`, `Core/` without platform subfolders → Cross-platform
345+
346+**Hard rule:** Never test more than 2 platforms unless user explicitly requests it.
347+
348+**Run Test on Specific iOS Device/Version:**
349+
350+When user requests a specific iOS version or device:
351+
352+1. **Find the UDID for that device/version combination**:
353+ ```bash
354+ # Example: Find iPhone Xs with iOS 18.5
355+ UDID=$(xcrun simctl list devices available --json | jq -r '
356+ .devices
357+ | to_entries
358+ | map(select(.key | contains("iOS-18-5")))
359+ | map(.value)
360+ | flatten
361+ | map(select(.name == "iPhone Xs"))
362+ | first
363+ | .udid
364+ ')
365+
366+ echo "Found UDID: $UDID"
367+ ```
368+
369+2. **Pass the UDID to the script**:
370+ ```bash
371+ pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios -DeviceUdid "$UDID"
372+ ```
373+
374+**Examples:**
375+- **"Run on iOS 18.5"** → Find iPhone Xs with iOS 18.5, get UDID, pass to script
376+- **"Run on iPhone 15"** → Find iPhone 15 (any iOS), get UDID, pass to script
377+- **"Run on iPhone 16 Pro with iOS 18.0"** → Find iPhone 16 Pro with iOS 18.0, get UDID, pass to script
378+
379+---
380+
381+## How the Template Works
382+
383+**The template ALWAYS does the same thing:**
384+
385+1. ✅ Verifies app launched successfully (WaitForElement)
386+2. ✅ Optionally runs automated UI tests (if you add them)
387+3. ✅ Exits WITHOUT closing the app (stays running for manual validation)
388+
389+**Usage:**
179390 ```bash
180−# Create a feature branch (NEVER work directly on main)
181−git checkout -b feature/issue-12345
391+# Copy the template
392+cp .github/scripts/templates/RunWithAppiumTest.template.cs CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs
182393
183−# Make commits normally
184−git add .
185−git commit -m "Fix: Description of the change"
394+# OPTIONAL: Add automated test logic in the TEST LOGIC section
395+# If you don't add test logic, it just verifies launch and exits
186396
187−# Push to remote (for new branches)
188−git push -u origin feature/issue-12345
397+# Run the script
398+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios
399+```
189400
190−# For subsequent pushes on the same branch
191−git push
401+**Result:**
402+- App launches and stays running
403+- You can manually validate in the simulator
404+- Test script exits without closing the app
405+
406+---
407+
408+## 🚨 CRITICAL: BuildAndRunSandbox.ps1 Script - ONLY Way to Deploy Sandbox
409+
410+**YOU MUST ALWAYS USE THIS SCRIPT. NEVER USE MANUAL `dotnet build`, `adb`, or `xcrun` COMMANDS.**
411+
412+### Script Location
413+`.github/scripts/BuildAndRunSandbox.ps1`
414+
415+### Basic Usage
416+```powershell
417+# Android
418+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform Android
419+
420+# iOS (auto-detects device)
421+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform iOS
422+
423+# iOS with specific device
424+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform iOS -DeviceUdid "YOUR-DEVICE-UDID"
192425 ```
193426
194−**When asked to update an existing PR:**
427+### What the Script Does Automatically
428+- ✅ **Device detection and boot** - Finds and boots simulator/emulator
429+- ✅ **UDID extraction** - Sets DEVICE_UDID environment variable
430+- ✅ **Fresh app build** - Builds Sandbox project for target platform
431+- ✅ **App deployment** - Installs and launches app
432+- ✅ **Appium server management** - Starts/stops Appium automatically
433+- ✅ **Log capture** - Saves device and Appium logs to `CustomAgentLogsTmp/Sandbox/`
434+- ✅ **Test execution** - Runs your Appium test script
435+
436+### Requirements Before Running
437+Copy and update test file (see Step 2 above). Template looks for "InstructionLabel" which doesn't exist - update first!
438+
439+**🚨 POST-TEST VALIDATION (MANDATORY):**
440+
441+After script completes, run Rule 4 validation checklist (see above). If ANY check fails: investigate, fix, rerun.
442+
443+**Key reminders**:
444+- HTTP 200 = element found, NOT test completed
445+- If no test actions in logs = FALSE SUCCESS
446+- If Appium can't find initial element = app crashed or AutomationIds wrong
447+
448+---
449+
450+### 📝 Note for User
451+
452+**Test scenario is ready in Sandbox for manual verification.**
453+
454+**To verify bug reproduction (optional):**
195455 ```bash
196−# Check out the PR branch directly (do NOT create a new branch off it)
197−gh pr checkout 12345
456+# 1. Revert the PR fix files
457+git checkout main -- [list specific fix files from PR]
198458
199−# Make fixes and commit to the PR branch
200−git add .
201−git commit -m "Fix: Description of the change"
459+# 2. Rerun test - bug should appear
460+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
461+
462+# 3. Restore fix
463+git checkout HEAD -- [fix files]
464+
465+# 4. Rerun test - bug should be gone
466+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
202467 ```
203−1. **STOP and ask the user** before pushing: "Changes are committed locally. Would you like me to push these changes to the PR?"
204−2. Exception: If the user's instructions explicitly include pushing, proceed without asking.
205468
206−### Documentation
207−- Update XML documentation for public APIs
208−- Follow existing code documentation patterns
209−- Update relevant docs in `docs/` folder when needed
469+This proves the test scenario correctly reproduces the bug.
210470
211−### Opening PRs
471+---
212472
213−All PRs are required to have this at the top of the description:
473+## 🔄 Iterative Testing Workflow (MANDATORY PROCESS)
214474
475+**🚨 CRITICAL**: This is THE workflow for Sandbox testing. Do NOT use manual `adb`/`xcrun` commands to bypass it.
476+
477+### The Required Loop
478+
215479 ```
216−<!-- Please let the below note in for people that find this PR -->
217−> [!NOTE]
218−> Are you waiting for the changes in this PR to be merged?
219−> It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you!
480+┌─────────────────────────────────────────────────────────────┐
481+│ 1. Update MainPage.xaml[.cs] with your test scenario │
482+│ - Add UI elements for reproduction │
483+│ - Add AutomationIds to all interactive elements │
484+│ - Add Console.WriteLine markers for debugging │
485+├─────────────────────────────────────────────────────────────┤
486+│ 2. Update Appium test to match your MainPage │
487+│ CustomAgentLogsTmp/Sandbox/RunWithAppiumTest.cs │
488+│ - Update element locators to match AutomationIds │
489+│ - Add test logic (tap buttons, verify labels) │
490+├─────────────────────────────────────────────────────────────┤
491+│ 3. Run BuildAndRunSandbox.ps1 │
492+│ pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform X │
493+├─────────────────────────────────────────────────────────────┤
494+│ 4. Validate results using SYSTEMATIC CHECKLIST │
495+│ - Step 1: Check for errors/exceptions │
496+│ - Step 2: Verify test actions (Tapping, etc.) │
497+│ - Step 3: Verify "Test completed" │
498+│ - Step 4: Check device logs for SANDBOX markers │
499+│ - Step 5-6: Screenshots and exit code │
500+├─────────────────────────────────────────────────────────────┤
501+│ 5. Did ALL validation checks pass? │
502+│ YES → Report success with summary (go to step 8) │
503+│ NO → Continue to step 6 │
504+├─────────────────────────────────────────────────────────────┤
505+│ 6. Investigate failure from captured logs │
506+│ - Read CustomAgentLogsTmp/Sandbox/android-device.log │
507+│ - Read CustomAgentLogsTmp/Sandbox/build-run-output.log │
508+│ - Identify root cause (element not found? crash?) │
509+├─────────────────────────────────────────────────────────────┤
510+│ 7. Fix the issue and LOOP BACK TO STEP 3 │
511+│ - Update MainPage if UI/code issue │
512+│ - Update RunWithAppiumTest.cs if test issue │
513+│ - Update both if AutomationId mismatch │
514+│ - Max 3 iterations before reporting as blocked │
515+├─────────────────────────────────────────────────────────────┤
516+│ 8. Report comprehensive summary to user │
517+│ - Test scenario source and justification │
518+│ - Validation results │
519+│ - Verdict (success/partial/issues/blocked) │
520+└─────────────────────────────────────────────────────────────┘
220521 ```
221522
222−Always put that at the top, without the block quotes. Without it, users will NOT be able to try the PR and your work will have been in vain!
523+### ❌ What NOT To Do
223524
525+**Never use manual commands during testing**:
526+- ❌ `adb logcat`, `adb shell`, `adb install`
527+- ❌ `xcrun simctl spawn`, `xcrun simctl install`
528+- ❌ `dotnet build`, `dotnet run`
224529
530+**Why**: Script already captured everything. Manual commands show CURRENT state, not test execution state.
225531
226−## Custom Agents and Skills
532+**✅ Correct**: Edit files → Rerun `BuildAndRunSandbox.ps1`
227533
228−The repository includes specialized custom agents and reusable skills for specific tasks.
534+### ✅ Correct Iteration Example
229535
230−### Skills vs Agents
536+**Most common case - Test fails to find element**:
537+```bash
538+# 1. Check what went wrong
539+grep "no such element" CustomAgentLogsTmp/Sandbox/build-run-output.log
231540
232−| Aspect | Skills | Agents |
233−|--------|--------|--------|
234−| **Invoke** | `/skill-name` or direct request | Delegate to agent |
235−| **Output** | Analysis, recommendations | Actions, changes applied |
236−| **Interaction** | Interactive discussion | Autonomous workflow |
237−| **Example** | `/learn-from-pr` → recommendations | learn-from-pr agent → applies changes |
541+# 2. Check what DOES exist in MainPage
542+grep AutomationId src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml
238543
239−### Available Custom Agents
544+# 3. Fix MainPage: Add AutomationIds
545+# Edit MainPage.xaml: <Button AutomationId="NavigateButton" ...
240546
241−1. **pr** - Sequential 4-phase workflow for reviewing and working on PRs
242− - **Use when**: A PR already exists and needs review or work, OR an issue needs a fix
243− - **Capabilities**: PR review, test verification, fix exploration, alternative comparison
244− - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX"
245− - **Do NOT use for**: Just running tests manually → Use `sandbox-agent`
547+# 4. Fix test: Update to match
548+# Edit RunWithAppiumTest.cs: App.WaitForElement("NavigateButton");
246549
247−2. **write-tests-agent** - Agent for writing tests. Determines test type (UI vs XAML) and invokes the appropriate skill (`write-ui-tests`, `write-xaml-tests`)
248− - **Use when**: Creating new tests for issues or PRs
249− - **Capabilities**: Test type determination (UI and XAML), skill invocation, test verification
250− - **Trigger phrases**: "write tests for #XXXXX", "create tests", "add test coverage"
550+# 5. Rerun
551+pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform android
552+```
251553
252−3. **sandbox-agent** - Specialized agent for working with the Sandbox app for testing, validation, and experimentation
253− - **Use when**: User wants to manually test PR functionality or reproduce issues
254− - **Capabilities**: Sandbox app setup, Appium-based manual testing, PR functional validation
255− - **Trigger phrases**: "test this PR", "validate PR #XXXXX in Sandbox", "reproduce issue #XXXXX", "try out in Sandbox"
256− - **Do NOT use for**: Code review (use pr agent), writing automated tests (use write-tests-agent)
554+**When validation passes**: Report success with comprehensive summary
257555
258−4. **learn-from-pr** - Extracts lessons from PRs and applies improvements to the repository
259− - **Use when**: After complex PR, want to improve instruction files/skills based on lessons learned
260− - **Capabilities**: Analyzes PR, identifies failure modes, applies improvements to instruction files, skills, code comments
261− - **Trigger phrases**: "learn from PR #XXXXX and apply improvements", "improve repo based on what we learned", "update skills based on PR"
262− - **Output**: Applied changes to instruction files, skills, architecture docs, code comments
263− - **Do NOT use for**: Analysis only without applying changes → Use `/learn-from-pr` skill instead
556+### When to Stop Iterating
264557
265−5. **release-readiness-agent** - Assesses ship-readiness for a .NET MAUI release branch — both **SR** (`release/*-srN`) and **Preview** (`release/*-previewN`)
266− - **Use when**: A release (SR or Preview) is approaching ship date and you need a synthesized verdict with WorkIQ/MCP enrichment on top of the deterministic report — **or** for a portfolio question across all active releases ("status on releases", "what needs attention across releases") where the user may not know which releases exist
267− - **Capabilities**: Resolves the branch (SR or Preview) from natural language, picks the right script (`Get-ReleaseReadiness.ps1` for SR, `Get-PreviewReadiness.ps1` for Preview), enriches `rejected-from-sr` candidates with WorkIQ context (SR lane), patches `UNKNOWN` ship-check rows via MCP (`maestro_default_channels`, `maestro_builds`), presents an overall verdict
268− - **Trigger phrases**: "is SR7 ready to ship", "release readiness for release/10.0.1xx-sr7", "survey the SR8 branch", "how does net11 preview6 look", "is preview6 ready to cut", "release readiness for release/11.0.1xx-preview6" — **plus portfolio / cross-release questions with no specific release named**: "give me a status on releases", "release status overview", "what's the status across all releases", "what needs attention across releases", "what's next for MAUI releases"
269− - **Output**: Verdict (Ready / Conditionally Ready / Not Ready) + per-candidate classification (SR) or per-section table (Preview) + actionable next steps
270− - **Do NOT use for**: Programmatic / scripted consumers that just need the raw JSON — use the `release-readiness` skill directly. Reviewing a single PR (use **pr**). Running tests manually (use **sandbox-agent**).
558+- ✅ **All validation checks pass** → Report success with detailed summary
559+- ❌ **Max 3 iterations reached** → **STOP and report**: "I wasn't able to reproduce the issue. What should I try next?"
560+- ❌ **Build fails repeatedly** → **STOP and report**: "I wasn't able to reproduce the issue due to build failures. What should I try next?"
561+- ❌ **Root cause unclear after log analysis** → **STOP and report**: "I wasn't able to reproduce the issue. What should I try next?"
562+- ❌ **Issue appears to be PR bug, not test** → **STOP and report findings to user**: "I wasn't able to reproduce the issue - it appears there may be an issue with [details]. What should I try next?"
563+- ❌ **Cannot reproduce the issue** → **STOP immediately**: "I wasn't able to reproduce the issue. What should I try next?"
271564
272−### Reusable Skills
565+**CRITICAL**: When you cannot reproduce or hit blockers, **PAUSE and ask the user**. Do NOT:
566+- ❌ Switch to a different branch (e.g., `git checkout main`)
567+- ❌ Try alternative approaches without asking first
568+- ❌ Change the workflow significantly without user guidance
273569
274−Skills are modular capabilities that can be invoked directly or used by agents. Located in `.github/skills/`:
570+### Mental Model: The Script is Your Robot
275571
276−#### User-Facing Skills
572+BuildAndRunSandbox.ps1 handles: build → deploy → capture logs → run test → report
277573
278−1. **pr-review** (`.github/skills/pr-review/SKILL.md`)
279− - **Purpose**: End-to-end PR review orchestrator — 3 phases: pr-preflight, try-fix, pr-report. Gate runs separately before this skill via Review-PR.ps1.
280− - **Trigger phrases**: "review PR #XXXXX", "work on PR #XXXXX", "fix issue #XXXXX", "continue PR #XXXXX"
281− - **Capabilities**: Multi-model fix exploration, alternative comparison, PR review recommendation
282− - **Do NOT use for**: Just running tests manually → Use `sandbox-agent`
283− - **Phase instructions** (in `.github/pr-review/`):
284− - `pr-preflight.md` — Context gathering from issue/PR
285− - `pr-report.md` — Final recommendation
286− - **Phase skill**: `try-fix` — Multi-model fix exploration
287− - **Note**: Gate (test verification) runs as a script step in `Review-PR.ps1` before this skill is invoked. Gate result is passed in the prompt.
574+**Your workflow**: Edit files → Run script → Read logs → Fix issues → Repeat
288575
289−2. **issue-triage** (`.github/skills/issue-triage/SKILL.md`)
290− - **Purpose**: Query and triage open issues that need milestones, labels, or investigation
291− - **Trigger phrases**: "find issues to triage", "show me old Android issues", "what issues need attention"
292− - **Scripts**: `init-triage-session.ps1`, `query-issues.ps1`, `record-triage.ps1`
576+---
293577
294−2. **find-reviewable-pr** (`.github/skills/find-reviewable-pr/SKILL.md`)
295− - **Purpose**: Finds open PRs in dotnet/maui and dotnet/docs-maui that need review
296− - **Trigger phrases**: "find PRs to review", "show milestoned PRs", "find partner PRs"
297− - **Scripts**: `query-reviewable-prs.ps1`
298− - **Categories**: P/0, milestoned, partner, community, recent, docs-maui
578+## Output Format
299579
300−3. **pr-finalize** (`.github/skills/pr-finalize/SKILL.md`)
301− - **Purpose**: Verifies PR title and description match actual implementation, AND performs code review for best practices before merge.
302− - **Trigger phrases**: "finalize PR #XXXXX", "check PR description for #XXXXX", "review commit message"
303− - **Used by**: Before merging any PR, when description may be stale
304− - **Note**: Does NOT require agent involvement or session markdown - works on any PR
305− - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` - only post comments. Approval is a human decision.
580+Provide a concise test summary:
306581
307−4. **code-review** (`.github/skills/code-review/SKILL.md`)
308− - **Purpose**: Reviews PR code changes for correctness, safety, and consistency with MAUI conventions. Walks through a MAUI-specific checklist covering handler lifecycle, platform code, safe area, threading, public API, and test patterns.
309− - **Trigger phrases**: "review code for PR #XXXXX", "code review PR #XXXXX", "review this PR's code"
310− - **Note**: Standalone skill — uses independence-first assessment (reads code before PR description to avoid anchoring bias). Can be used by any agent or invoked directly.
311− - **🚨 CRITICAL**: NEVER use `--approve` or `--request-changes` — only post comments. Approval is a human decision.
582+```markdown
583+## PR Testing Summary
312584
313−5. **learn-from-pr** (`.github/skills/learn-from-pr/SKILL.md`)
314− - **Purpose**: Analyzes completed PR to identify repository improvements (analysis only, no changes applied)
315− - **Trigger phrases**: "what can we learn from PR #XXXXX?", "how can we improve agents based on PR #XXXXX?"
316− - **Used by**: After complex PRs, when agent struggled to find solution
317− - **Output**: Prioritized recommendations for instruction files, skills, code comments
318− - **Note**: For applying changes automatically, use the learn-from-pr agent instead
585+**PR**: #XXXXX - [Title]
586+**Platform Tested**: Android/iOS
587+**Issue**: [Brief description]
319588
320−6. **write-ui-tests** (`.github/skills/write-ui-tests/SKILL.md`)
321− - **Purpose**: Creates UI tests for GitHub issues and verifies they reproduce the bug
322− - **Trigger phrases**: "write UI tests for #XXXXX", "create UI test for issue", "add UI test coverage"
323− - **Output**: Test files that fail without fix, pass with fix
589+---
324590
325−7. **write-xaml-tests** (`.github/skills/write-xaml-tests/SKILL.md`)
326− - **Purpose**: Creates XAML unit tests for XAML parsing, compilation, and source generation
327− - **Trigger phrases**: "write XAML tests for #XXXXX", "test XamlC behavior", "reproduce XAML parsing bug"
328− - **Output**: Test files for Controls.Xaml.UnitTests
591+### Test Scenario Setup
329592
330−9. **verify-tests-fail-without-fix** (`.github/skills/verify-tests-fail-without-fix/SKILL.md`)
331− - **Purpose**: Verifies tests catch the bug before fix and pass with fix. Auto-detects test type (UI, device, unit, XAML) and dispatches to the appropriate runner.
332− - **Two modes**: Verify failure only (test creation) or full verification (test + fix)
333− - **Used by**: After creating tests, before considering PR complete
593+**🚨 REQUIRED - Source of Test Scenario**:
594+- **Source**: [From issue reproduction / From PR UITest / Custom scenario]
595+- **Why this source**: [e.g., "Issue #XXXXX provides detailed repro steps" / "PR includes UITest that demonstrates the fix" / "No repro available, created scenario based on PR code changes"]
596+- **Link to source**: [URL to issue comment with repro, or path to UITest file]
334597
335−10. **run-integration-tests** (`.github/skills/run-integration-tests/SKILL.md`)
336− - **Purpose**: Build, pack, and run .NET MAUI integration tests locally
337− - **Trigger phrases**: "run integration tests", "test templates locally", "run macOSTemplates tests", "run RunOniOS tests"
338− - **Categories**: Build, WindowsTemplates, macOSTemplates, Blazor, MultiProject, Samples, AOT, RunOnAndroid, RunOniOS
339− - **Note**: **ALWAYS use this skill** instead of manual `dotnet test` commands for integration tests
598+**What was tested**:
599+- [Specific actions taken - e.g., "Tap 'Toggle RTL' button, then tap 'Show Dialog' button"]
600+- [UI elements involved - e.g., "Button with AutomationId='ToggleButton', Dialog with Label"]
601+- [Expected behavior - e.g., "Dialog should appear with correct RTL padding on label"]
340602
341−11. **dependency-flow** (`.github/skills/dependency-flow/SKILL.md`)
342− - **Purpose**: MAUI-specific dependency flow rules, channel conventions, and feed lookup workflows
343− - **Trigger phrases**: "feeds for .NET MAUI X.Y.Z", "where is MAUI build", "promote build to public feed", "what channels is MAUI on", "subscription health for MAUI"
344− - **Wraps**: `maestro-cli` skill (from `dotnet-dnceng@dotnet-arcade-skills` plugin) and maestro MCP tools
345− - **Note**: Provides MAUI-specific guardrails on top of core Maestro/darc operations — channel naming, safety deny-list, input validation, and prompt injection defense
603+---
346604
347−12. **release-readiness** (`.github/skills/release-readiness/SKILL.md`)
348− - **Purpose**: Deterministic ship-readiness engine for .NET MAUI release branches — both **SR** (`release/*-srN`) and **Preview** (`release/*-previewN`). Surveys CI, computes what's actually shipping, classifies open regressions, identifies port candidates and rejected backports
349− - **Trigger phrases**: "release readiness for SRN", "is SR7 ready to ship", "survey the SR branch", "release readiness for preview6", "how does preview6 look (deterministic)", "status across all releases" (reads the live `[Release Readiness]` tracker issues by body marker — no survey re-run needed)
350− - **Scripts**: `Get-ReleaseReadiness.ps1` (SR lane), `Get-PreviewReadiness.ps1` (Preview lane), `Find-ReleaseReadinessTrackers.ps1` (tracker discovery)
351− - **Output**: JSON + Markdown report, list of source PRs, classification of regression issues (in-sr-active, rejected-from-sr, no-fix-yet, etc.)
352− - **Note**: Deterministic and reproducible — no MCP, no LLM judgment. Use **this skill directly** when you need raw output for a script, dashboard, cron job, or programmatic consumer. For natural-language verdict synthesis with WorkIQ enrichment, use the **`release-readiness-agent`** instead.
605+### Test Results WITH PR Fix
353606
354−#### Internal Skills (Used by Agents)
607+**Observed Behavior**:
608+- [What happened when running the test]
609+- [Appium test results]
610+- [Relevant log excerpts]
355611
356−13. **try-fix** (`.github/skills/try-fix/SKILL.md`)
357− - **Purpose**: Proposes ONE independent fix approach, applies it, tests, records result with failure analysis, then reverts
358− - **Used by**: pr agent Phase 3 (Fix phase) - rarely invoked directly by users
359− - **Behavior**: Reads prior attempts to learn from failures. Max 5 attempts per session.
360− - **Output**: Updates session markdown with attempt results and failure analysis
612+**Screenshots**: [Reference if taken, but not for validation]
361613
362−### Using Custom Agents
614+---
363615
364−**Delegation Policy**: When user request matches agent trigger phrases, **ALWAYS delegate to the appropriate agent immediately**. Do not ask for permission or explain alternatives unless the request is ambiguous.
616+### Verdict
365617
366−**Examples of correct delegation**:
367−- User: "Review PR #12345" → Immediately invoke **pr** agent
368−- User: "Test this PR" → Immediately invoke **sandbox-agent**
369−- User: "Fix issue #67890" (no PR exists) → Suggest using `/delegate` command
370−- User: "Write tests for issue #12345" → Immediately invoke **write-tests-agent**
371−- User: "Is SR7 ready to ship?" → Immediately invoke **release-readiness-agent**
372−- User: "How does net11 preview6 look?" → Immediately invoke **release-readiness-agent**
373−- User: "Give me a status on releases / what needs attention across releases?" → Immediately invoke **release-readiness-agent** (portfolio mode — it enumerates active releases by reading the `[Release Readiness]` tracker issues; don't ask "which release?")
374−- User: "Give me the raw release-readiness JSON for SR8" → Use the **release-readiness** skill directly (no enrichment needed)
618+✅ **FIX VALIDATED** - Test scenario completes successfully, expected behavior observed
619+OR
620+⚠️ **PARTIAL** - Fix appears to work but [note any concerns]
621+OR
622+❌ **ISSUES FOUND** - [Specific problems encountered]
623+OR
624+🚫 **CANNOT TEST** - [Build failures, setup issues, etc.]
375625
376−**When NOT to delegate**:
377−- User asks "What does PR #12345 do?" → Informational query, handle yourself
378−- User asks "How do I test PRs?" → Documentation query, handle yourself
379−- User has follow-up questions after agent completes → Continue the conversation yourself
626+---
627+
628+### Notes for User
629+- Test scenario is set up in Sandbox and ready for manual verification if needed
630+- To verify bug reproduction without fix, revert PR changes: `git checkout main -- [fix files]`
631+- Then rerun: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]`
632+```
633+
634+---
635+
636+## Best Practices
637+
638+1. **Use issue reproduction when available** - Most reliable test scenario
639+2. **Adapt PR's UITests if no repro** - They're already designed to test the fix
640+3. **Validate programmatically, reference visually** - Use Appium element queries for validation, screenshots only for additional context
641+4. **Use colored backgrounds** - Makes layout issues visible
642+5. **Add console markers** - Easy to grep logs
643+6. **Test multiple iterations** - Race conditions need multiple runs (3-5 times)
644+7. **Leave Sandbox as-is** - User will iterate on it after your testing
645+8. **Document your test scenario thoroughly** - Include source (issue/UITest/custom), why you chose it, specific actions, and expected behavior so user can verify
646+
647+**Screenshot Usage**:
648+- ✅ Take screenshots for **context and reference** (e.g., showing layout before/after)
649+- ✅ Include in report if they provide **additional insight** beyond what logs show
650+- ❌ Do NOT rely on screenshots as **primary validation** - use Appium element queries and log analysis
651+- ❌ Do NOT take screenshots just to show "it works" - validation should come from test assertions
652+
653+---
654+
655+## Log Capture and Review
656+
657+### Where Logs Are Saved
658+
659+After running BuildAndRunSandbox.ps1, all logs are in `CustomAgentLogsTmp/Sandbox/`:
660+
661+1. **Android**: `CustomAgentLogsTmp/Sandbox/android-device.log`
662+2. **iOS**: `CustomAgentLogsTmp/Sandbox/ios-device.log`
663+3. **Appium**: `CustomAgentLogsTmp/Sandbox/appium.log`
664+
665+### Viewing Logs
666+
667+```bash
668+# View device logs
669+cat CustomAgentLogsTmp/Sandbox/android-device.log
670+# or
671+cat CustomAgentLogsTmp/Sandbox/ios-device.log
672+
673+# Search for specific output
674+grep "TEST OUTPUT" CustomAgentLogsTmp/Sandbox/android-device.log
675+
676+# View Appium logs
677+cat CustomAgentLogsTmp/Sandbox/appium.log
678+```
679+
680+### 📝 Adding Debug Logging to Your Test Scenario
681+
682+**Use `Console.WriteLine` for logging** - it works on all platforms.
683+
684+```csharp
685+// Use a unique prefix for easy grep
686+Console.WriteLine("SANDBOX: Button clicked");
687+Console.WriteLine($"SANDBOX: Value is {myValue}");
688+```
689+
690+**Searching logs:**
691+```bash
692+grep "SANDBOX" CustomAgentLogsTmp/Sandbox/android-device.log
693+grep "SANDBOX" CustomAgentLogsTmp/Sandbox/ios-device.log
694+grep "SANDBOX" CustomAgentLogsTmp/Sandbox/catalyst-device.log
695+```
696+
697+---
698+
699+## 🚨 ABSOLUTE RULE: BuildAndRunSandbox.ps1 is THE ONLY Deployment Method
700+
701+**THIS IS MANDATORY. NOT A SUGGESTION.**
702+
703+❌ If typing `adb`/`xcrun` commands during testing → STOP. You're violating the workflow.
704+
705+**Why**: Manual commands show CURRENT state, not test execution state. Script already captured correct logs during test.
706+
707+**❌ NEVER during testing**: `adb logcat`, `adb install`, `adb shell`, `xcrun simctl install/spawn`, `dotnet build/run`
708+
709+**✅ ONLY exception**: Finding/booting specific iOS device BEFORE running script (`xcrun simctl list/boot`)
710+
711+**Correct workflow**:
712+1. Edit files (MainPage, RunWithAppiumTest.cs)
713+2. Run: `pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform X`
714+3. Analyze logs in `CustomAgentLogsTmp/Sandbox/` (android-device.log, appium.log)
715+4. Fix issues, rerun script
716+
717+**Expected logs**: `android-device.log` or `ios-device.log`, `appium.log`, `RunWithAppiumTest.cs`, optional screenshots
718+
719+---
720+
721+## Troubleshooting & Recovery
722+
723+**Retry up to 3 times before reporting as blocked.** After each failure: analyze logs → fix → rerun script.
724+
725+### Common Issues
726+
727+| Issue | Recovery | Max Retries |
728+|-------|----------|-------------|
729+| Build error | Check SDK version, `dotnet tool restore` | 2 |
730+| App crash | Check stack trace in device log, fix code/XAML | 3 |
731+| Element not found | Verify AutomationIds match, check app loaded | 2 |
732+| Fast Deployment (Android) | Add `appium:noReset` capability | 1 |
733+| XAML parse error | Verify event handler exists in code-behind | 2 |
734+
735+### Element Not Found Debugging
736+
737+🚨 If Appium can't find initial element, app is NOT running correctly.
738+
739+**Check**:
740+```bash
741+# Look for crashes
742+grep -i "FATAL\|crash\|exception" CustomAgentLogsTmp/Sandbox/android-device.log | tail -20
743+
744+# Verify app launched
745+grep "SANDBOX.*MainPage" CustomAgentLogsTmp/Sandbox/android-device.log
746+```
747+
748+**Root causes**: App crashed, XAML parse error, AutomationId mismatch, Android Fast Deployment
749+
750+### When to Stop & Report
751+- ✅ **Continue**: Minor warnings, non-critical timeouts, platform differences
752+- ❌ **Stop and ask user**: Can't checkout PR, build fails after max retries, SDK mismatch, root cause unclear, cannot reproduce issue
753+
754+**When blocked, ALWAYS report to user with this format**:
755+```markdown
756+I wasn't able to reproduce the issue. Here's what I tried:
757+
758+1. [What I attempted]
759+2. [Issues encountered]
760+3. [Current state of reproduction attempt]
761+
762+What should I try next?
763+```
764+
765+**DO NOT** try alternative approaches without asking first. **DO NOT** switch branches.
766+
767+### Test Shows Unexpected Behavior
768+**Action**: Document and report
769+
770+```markdown
771+⚠️ Unexpected behavior during testing
772+
773+**What I expected**: [Based on issue description]
774+
775+**What I observed**: [Actual behavior]
776+
777+**Test scenario**: [What was tested]
778+
779+**Logs**: [Relevant excerpts]
780+
781+**Question for user**: Is this expected behavior, or does this indicate an issue?
782+```
783+
784+---
785+
786+## Common Mistakes to Avoid
787+
788+- ❌ Using TestCases.HostApp for manual PR validation (use Sandbox)
789+- ❌ Manual build/deploy commands instead of BuildAndRunSandbox.ps1
790+- ❌ Testing only one platform when PR affects multiple
791+- ❌ Using screenshots for validation (use Appium element queries)
792+- ❌ Creating test scenario without checking issue for reproduction steps
793+- ❌ Ignoring PR's existing UITests when available
794+- ❌ Cleaning up or reverting Sandbox changes (user will iterate on it)
795+
796+**Testing Tips**:
797+- For layout bugs: Use `element.GetRect()` to measure positions
798+- For SafeArea PRs: Measure child content position, not parent size
799+- Add `Console.WriteLine("SANDBOX: ...")` markers for debugging
800+
801+---
802+
803+## Appendix: Cleanup (Only When User Requests)
804+
805+⚠️ **DO NOT clean up after testing** - Leave Sandbox as-is so user can iterate on it.
806+
807+Only use these commands if the **user explicitly requests cleanup**:
808+
809+### Sandbox App Cleanup (User Request Only)
810+```bash
811+# Revert all changes to Sandbox app
812+git checkout -- src/Controls/samples/Controls.Sample.Sandbox/
813+```
814+
815+### Sandbox Test Files Cleanup (User Request Only)
816+```bash
817+# Remove Appium test directory (gitignored)
818+rm -rf CustomAgentLogsTmp/Sandbox/
819+```
820+
