- name
- try-fix
- description
- Attempts ONE alternative fix for a bug, tests it empirically, and reports results. ALWAYS explores a DIFFERENT approach from existing PR fixes. Use when CI or an agent needs to try independent fix alternatives. Invoke with problem description, test command, target files, and optional hints.
- compatibility
- Requires PowerShell, git, .NET MAUI build environment, Android/iOS device or emulator
# Try Fix Skill
Attempts ONE fix for a given problem. Receives all context upfront, tries a single approach, tests it, and reports what happened.
## Activation Guard
🚨 **This skill is ONLY for proposing and testing code fixes.** Do NOT activate for:
- Code review requests ("review this PR", "check code quality")
- PR summaries or descriptions ("what does this PR do?")
- Test-only requests ("run tests", "check CI status")
- General questions about code or architecture
If the prompt does not include a **problem to fix** and a **test command to verify**, this skill should not run.
## Core Principles
1. **Always run once activated** - Never question whether to run. The invoker decides WHEN, you decide WHAT alternative to try
2. **Single-shot** - Each invocation = ONE fix idea, tested, reported
3. **Alternative-focused** - Always propose something DIFFERENT from existing fixes (review PR changes first)
4. **Empirical** - Actually implement and test, don't just theorize
5. **Context-driven** - Work with what's provided and git history; don't search external sources
6. **Script-only restoration** - The ONLY permitted cleanup command is
`pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore`. Never use
`git checkout`, `git clean`, `git restore`, `git reset`, or `git stash` to
revert or clean changes, including after artifacts have been captured.
7. **Baseline-file boundary** - After Step 2, modify ONLY files listed in
`.github/.baseline-state.json` under `RevertedFiles`. The restore script
tracks only those original fix files; editing any other tracked file makes
restoration incomplete. If the state file is absent, or its `NewFiles`
array is non-empty, report `Blocked` before editing: added production files
are not safely restorable. If the approach requires another tracked file,
report `Blocked` instead of editing it.
8. **Preserve pre-existing untracked paths** - Never modify or delete an
untracked file or directory that existed before the attempt. Evaluators may
inject the loaded skill as an untracked directory such as `try-fix/`; leave
it exactly as found even when `git status --short` lists it. It is
harness-owned input, not attempt-created drift. The restore script is the
only cleanup step; do not use `rm`, `Remove-Item`, or another filesystem
command to make the worktree appear clean.
9. **Wait for command completion** - If a shell tool reports that a command is
still running and returns a `shellId`, call `read_bash` with that exact
`shellId` and wait for the completed result. Never proceed, report, or end
the session while baseline, test, artifact, self-review, or restore work is
still running.
10. **Contain attempt artifacts** - Create every log, snapshot, state marker, and
scratch file under `$OUTPUT_DIR`. Never persist `$OUTPUT_DIR` or other shell
state in `.github/`, the repository root, or another workspace path. Shell
variables do not persist between tool calls, so redeclare the same literal
`$OUTPUT_DIR` at the start of each later shell command instead of writing a
repository marker file.
**Every invocation runs all 11 Workflow steps below.** Step 6 (Expert Self-Review) is performed inline against `.github/agents/maui-expert-reviewer.md` — do NOT spawn the `@maui-expert-reviewer` sub-agent. Step 7.5 refreshes the self-review if the test loop modified code so the recorded findings reflect the final diff. Step 8 enforces this via a file-existence gate on `reviewer-findings.json`. Before returning the final report, verify that Step 9 ran with the exact script-only restore command above; if it did not, run it before responding.
## ⚠️ CRITICAL: Sequential Execution Only
🚨 **Try-fix runs MUST be executed ONE AT A TIME - NEVER in parallel.**
**Why:** Each try-fix run:
- Modifies the same target source files
- Uses the same device/emulator for testing
- Runs EstablishBrokenBaseline.ps1 which reverts files to a known state
**If run in parallel:**
- Multiple agents will overwrite each other's code changes
- Device tests will interfere with each other
- Baseline script will conflict, causing unpredictable file states
- Results will be corrupted and unreliable
**Correct pattern:** Run attempt-1, wait for completion, then run attempt-2, etc.
## Inputs
All inputs are provided by the invoker (CI, agent, or user).
| Input | Required | Description |
|-------|----------|-------------|
| Problem | Yes | Description of the bug/issue to fix |
| Test command | Yes | **Repository-specific script** to build and test. Use `BuildAndRunHostApp.ps1` for UI tests, `Run-DeviceTests.ps1` for device tests, or `dotnet test` for unit tests. The correct command is determined by the test type detected in the PR. **ALWAYS use the appropriate script - NEVER manually build/compile.** |
| Target files | Yes | Files to investigate; any file absent from the baseline state's `RevertedFiles` is read-only |
| Platform | Yes | Target platform (`android`, `ios`, `windows`, `maccatalyst`) |
| Hints | Optional | Suggested approaches, prior attempts, or areas to focus on |
| Baseline | Optional | Git ref or instructions for establishing broken state (default: current state) |
## Outputs
Results reported back to the invoker:
| Field | Description |
|-------|-------------|
| `approach` | What fix was attempted (brief description) |
| `files_changed` | Which files were modified |
| `result` | `Pass`, `Fail`, or `Blocked` |
| `analysis` | Why it worked, or why it failed and what was learned |
| `diff` | The actual code changes made (for review) |
| `findings_count` | Number of self-review findings recorded (0 = clean self-review) |
## Output Structure (MANDATORY)
**FIRST STEP: Create output directory before doing anything else.**
```powershell
# Set issue/PR number explicitly (from branch name, PR context, or manual input)
$IssueNumber = "<ISSUE_OR_PR_NUMBER>" # Replace with actual number
# Find next attempt number
$tryFixDir = "CustomAgentLogsTmp/PRState/$IssueNumber/PRAgent/try-fix"
$existingAttempts = (Get-ChildItem "$tryFixDir/attempt-*" -Directory -ErrorAction SilentlyContinue).Count
$attemptNum = $existingAttempts + 1
# Create output directory
$OUTPUT_DIR = "$tryFixDir/attempt-$attemptNum"
New-Item -ItemType Directory -Path $OUTPUT_DIR -Force | Out-Null
Write-Host "Output directory: $OUTPUT_DIR"
```
Keep this path from the command output and redeclare it in each subsequent
shell invocation, for example:
```powershell
$OUTPUT_DIR = "CustomAgentLogsTmp/PRState/<ISSUE_OR_PR_NUMBER>/PRAgent/try-fix/attempt-1"
```
Do not create `.github/.try-fix-output-dir`, `.try-fix-output-dir`, or any
equivalent repository marker. The only attempt artifacts belong under
`$OUTPUT_DIR`.
**Required files to create in `$OUTPUT_DIR`:**
| File | When to Create | Content |
|------|----------------|---------|
| `baseline.log` | After Step 2 (Baseline) | Output from EstablishBrokenBaseline.ps1 proving baseline was established |
| `approach.md` | After Step 4 (Design) | What fix you're attempting and why it's different from existing fixes |
| `reviewer-findings.json` | After Step 6 (Self-Review), refreshed by Step 7.5 | JSON array of self-review findings — `[]` when clean. **MUST reflect the final diff.** |
| `reviewer-findings.diff` | After Step 6 (Self-Review), refreshed by Step 7.5 | Snapshot of `git diff` at the time the self-review was written. Step 7.5 compares this to the post-test-loop diff to detect drift. |
| `result.txt` | After Step 7 (Test) | Single word: `Pass`, `Fail`, or `Blocked` |
| `fix.diff` | After Step 7 (Test) | Output of `git diff` showing your changes |
| `test-output.log` | After Step 7 (Test) | Full output from test command |
| `analysis.md` | After Step 8 (Capture) | Why it worked/failed, insights learned, and a one-line self-review summary |
**Example approach.md:**
```markdown
## Approach: Geometric Off-Screen Check
Skip RequestApplyInsets for views completely off-screen using simple bounds check:
`viewLeft >= screenWidth || viewRight <= 0 || viewTop >= screenHeight || viewBottom <= 0`
**Different from existing fix:** Current fix uses HashSet tracking. This approach uses pure geometry with no state.
```
**Example result.txt:**
```
Pass
```
## Completion Criteria
The skill is complete when:
- [ ] Problem understood from provided context
- [ ] ONE fix approach designed and implemented
- [ ] Fix tested with provided test command (iterated up to 3 times if errors/failures)
- [ ] Either: Tests PASS ✅, or exhausted attempts and documented why approach won't work ❌
- [ ] **Expert self-review performed inline (Step 6) and `reviewer-findings.json` written** — `[]` if clean. **Refreshed by Step 7.5 if the test loop modified code, so the saved findings reflect the final diff.**
- [ ] Analysis provided (success explanation or failure reasoning with evidence)
- [ ] Artifacts saved to output directory (verified by Step 8 file-existence gate)
- [ ] Baseline target files restored with no attempt-created changes; pre-existing untracked harness inputs remain untouched
- [ ] Results reported to invoker (including `findings_count`)
🚨 **CRITICAL: What counts as "Pass" vs "Fail"**
| Scenario | Result | Explanation |
|----------|--------|-------------|
| Test command runs, tests pass | ✅ **Pass** | Actual validation |
| Test command runs, tests fail | ❌ **Fail** | Fix didn't work |
| Code compiles but no device available | ⚠️ **Blocked** | Device/emulator unavailable - report with explanation |
| Code compiles but test command errors | ❌ **Fail** | Infrastructure issue is still a failure |
| Code doesn't compile | ❌ **Fail** | Fix is broken |
**NEVER claim "Pass" based on:**
- ❌ "Code compiles successfully" alone
- ❌ "Code review validates the logic"
- ❌ "The approach is sound"
- ❌ "Device was unavailable but fix looks correct"
**Pass REQUIRES:** The test command executed AND reported test success.
**If device/emulator is unavailable:** Report `result.txt` = `Blocked` with explanation. Do NOT manufacture a Pass.
**Exhaustion criteria:** Stop after 3 iterations if:
1. Code compiles but tests consistently fail for same reason
2. Root cause analysis reveals fundamental flaw in approach
3. Alternative fixes would require completely different strategy
**Never stop due to:** Compile errors (fix them), infrastructure blame (debug your code), giving up too early.
> **Session limits:** Each try-fix *invocation* allows up to 3 compile/test iterations. The *calling orchestrator* controls how many invocations (attempts) to run per session (typically 4-5 as part of pr-review Phase 3).
---
## Workflow
### Step 1: Understand the Problem and Review Existing Fixes
**MANDATORY:** Review what has already been tried:
1. **Check for existing PR changes:**
```bash
git diff origin/main HEAD --name-only
```
- Review what files were changed
- Read the actual code changes to understand the current fix approach
2. **Review prior attempts if any are known:**
- Note which approaches failed and WHY
- Note which approaches partially succeeded
3. **Identify what makes your approach DIFFERENT:**
- Don't repeat the same logic/pattern as existing fixes
- Think of alternative approaches: different algorithm, different location, different strategy
- If existing fix modifies X, consider modifying Y instead
- If existing fix adds logic, consider removing/simplifying instead
**Examples of alternatives:**
- Existing fix: Add caching → Alternative: Change when updates happen
- Existing fix: Fix in handler → Alternative: Fix in platform layer
**Review the provided context:**
- What is the bug/issue?
- What test command verifies the fix?
- What files should be investigated?
- Are there hints about what to try or avoid?
**Do NOT search for external context.** Work with what's provided and the git history.
### Step 2: Establish Baseline (MANDATORY)
🚨 **ONLY use EstablishBrokenBaseline.ps1 — NEVER use `git checkout`, `git restore`, or `git reset` to revert fix files.**
The script auto-restores any previous baseline, tracks state, and prevents loops.
Manual git commands bypass all of this and WILL cause infinite loops in CI.
```powershell
pwsh .github/scripts/EstablishBrokenBaseline.ps1 *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/baseline.log"
```
If this command continues in the background, wait for its matching `shellId`
with `read_bash` until it completes. The baseline is not established merely
because the initial shell invocation returned.
**Verify baseline was established:**
```powershell
Select-String -Path "$OUTPUT_DIR/baseline.log" -Pattern "Baseline established"
```
Read `.github/.baseline-state.json` after this command. Its `RevertedFiles`
array is the complete modification allow-list for the attempt. Target files
outside that array may be inspected but MUST NOT be edited. If the state file
was not created, or `NewFiles` contains any path, report `Blocked` immediately
and proceed to Step 9 without modifying tracked files; the restore script does
not safely restore added production files.
**If the script fails with "No fix files detected":** Report as `Blocked` — do NOT switch branches.
**If something fails mid-attempt:** `pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore`
### Step 3: Analyze Target Files
Read the target files to understand the code.
**Verify the platform code path before implementing.** Check which platform-specific file actually executes for the target scenario:
- Files named `.iOS.cs` compile for both iOS AND MacCatalyst
- Files named `.Android.cs` only compile for Android
- Some platforms use Legacy implementations (e.g., iOS NavigationPage uses `NavigationPage.Legacy.cs`, not `MauiNavigationImpl`)
If unsure which code path runs, check `AppHostBuilderExtensions` or handler registration to confirm.
**Key questions:**
- What is the root cause of this bug?
- Where should the fix go?
- What's the minimal change needed?
### Step 4: Design ONE Fix
Based on your analysis and any provided hints, design a single fix approach:
- Which file(s) to change
- What the change is
- Why you think this will work
**"Different" means different ROOT CAUSE hypothesis, not just different code location.**
- ❌ Bad: PR checks `adapter == null` in OnMeasure; you check `adapter == null` in OnLayout (same root cause assumption — just a different call site)
- ✅ Good: PR checks `adapter == null`; you prevent disposal from happening during measure (different root cause hypothesis)
**If hints suggest specific approaches**, prioritize those.
**IMMEDIATELY create `approach.md`** in your output directory:
```powershell
@"
## Approach: [Brief Name]
[Description of what you're changing and why]
**Prior approach avoided:** [Name every relevant existing/prior approach, their shared failure mechanism, and why they failed, or N/A]
**Mechanism-level difference:** [Explain the full cause-to-effect chain showing why the new mechanism avoids that failure, not merely the code location]
"@ | Set-Content "$OUTPUT_DIR/approach.md"
```
### Step 5: Apply the Fix
Implement your fix. Use `git status --short` and `git diff` to track changes.
### Step 6: Expert Self-Review (MANDATORY — runs BEFORE testing)
🚨 **You perform this self-review yourself. Do NOT spawn the `@maui-expert-reviewer` sub-agent.** Step 8's file-existence gate enforces that `reviewer-findings.json` is written every attempt.
This step runs BEFORE testing so you can catch design flaws before spending time on build+test cycles.
**Procedure:**
1. **Read the rules.** View these specific sections of `.github/agents/maui-expert-reviewer.md`:
- **`## Overarching Principles`** (8 numbered principles, near the top of the file) — apply to every fix
- **`## Dimension Routing`** + **`### Always-Active Dimensions`** — pick the dimensions that match your changed files
- For each routed dimension, jump to its CHECK list under `## Review Dimensions` (e.g., `### 1. Layout Measure-Arrange Correctness`)
You only need the dimensions that match the files you actually touched plus the always-active ones — typically 3–6 sections, not all 30.
2. **Identify your changed files:**
```powershell
git diff --name-only HEAD
```
If you have NO code changes (e.g., Blocked because no device available before any fix was applied), still proceed to step 4 and write `'[]'` — the artifact gate is the enforcement mechanism.
3. **Walk your diff against the rules:**
- For each Overarching Principle → does your diff violate it?
- For each routed dimension → walk every CHECK rule against the relevant hunks
- Always-Active dimensions (Logic and Correctness, Regression Prevention, Complexity Reduction) → apply regardless of file paths
- Be honest. If unsure, flag it.
View on GitHub