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.
Attempts ONE fix for a given problem. Receives all context upfront, tries a single approach, tests it, and reports what happened.
🚨 This skill is ONLY for proposing and testing code fixes. Do NOT activate for:
If the prompt does not include a problem to fix and a test command to verify, this skill should not run.
Every invocation: Review existing fixes → Think of DIFFERENT approach → Implement and test → Report results
🚨 Try-fix runs MUST be executed ONE AT A TIME - NEVER in parallel.
Why: Each try-fix run:
If run in parallel:
Correct pattern: Run attempt-1, wait for completion, then run attempt-2, etc.
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 for the fix |
| 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) |
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) |
FIRST STEP: Create output directory before doing anything else.
# 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"
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 |
result.txt | After Step 6 (Test) | Single word: Pass, Fail, or Blocked |
fix.diff | After Step 6 (Test) | Output of git diff showing your changes |
test-output.log | After Step 6 (Test) | Full output from test command |
analysis.md | After Step 6 (Test) | Why it worked/failed, insights learned |
Example approach.md:
## 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
The skill is complete when:
🚨 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:
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:
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).
MANDATORY: Review what has already been tried:
Check for existing PR changes:
git diff origin/main HEAD --name-only
Review prior attempts if any are known:
Identify what makes your approach DIFFERENT:
Examples of alternatives:
Review the provided context:
Do NOT search for external context. Work with what's provided and the git history.
🚨 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.
pwsh .github/scripts/EstablishBrokenBaseline.ps1 *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/baseline.log"
Verify baseline was established:
Select-String -Path "$OUTPUT_DIR/baseline.log" -Pattern "Baseline established"
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
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:
.iOS.cs compile for both iOS AND MacCatalyst.Android.cs only compile for AndroidNavigationPage.Legacy.cs, not MauiNavigationImpl)
If unsure which code path runs, check AppHostBuilderExtensions or handler registration to confirm.Key questions:
Based on your analysis and any provided hints, design a single fix approach:
"Different" means different ROOT CAUSE hypothesis, not just different code location.
adapter == null in OnMeasure; you check adapter == null in OnLayout (same root cause assumption — just a different call site)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:
@"
## Approach: [Brief Name]
[Description of what you're changing and why]
**Different from existing fix:** [How this differs from PR's current approach]
"@ | Set-Content "$OUTPUT_DIR/approach.md"
Implement your fix. Use git status --short and git diff to track changes.
🚨 CRITICAL: ALWAYS use the provided test command script - NEVER manually build/compile.
For .NET MAUI repository: Use the test script matching the test type:
| Test Type | Command |
|---|---|
| UITest | pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform <platform> -TestFilter "<filter>" |
| DeviceTest | pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project <project> -Platform <platform> -TestFilter "<filter>" |
| UnitTest | dotnet test <project.csproj> --filter "<filter>" |
# Capture output to test-output.log while also displaying it
# Example for UI tests:
pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform <platform> -TestFilter "<filter>" *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/test-output.log"
# Example for device tests:
pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project <project> -Platform <platform> -TestFilter "<filter>" *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/test-output.log"
Testing Loop (Iterate until SUCCESS or exhausted):
Behavioral constraints:
See references/compile-errors.md for error patterns and iteration examples.
Before reverting, save ALL required files to $OUTPUT_DIR:
# 1. Save result (MUST be exactly "Pass", "Fail", or "Blocked")
"Pass" | Set-Content "$OUTPUT_DIR/result.txt" # or "Fail"
# 2. Save the diff
git diff | Set-Content "$OUTPUT_DIR/fix.diff"
# 3. Save test output (should already exist from Step 6)
# Copy-Item "path/to/test-output.log" "$OUTPUT_DIR/test-output.log"
# 4. Save analysis
@"
## Analysis
**Result:** Pass/Fail/Blocked
**What happened:** [Description of test results]
**Why it worked/failed:** [Root cause analysis]
**Insights:** [What was learned that could help future attempts]
"@ | Set-Content "$OUTPUT_DIR/analysis.md"
Verify all required files exist:
@("baseline.log", "approach.md", "result.txt", "fix.diff", "analysis.md", "test-output.log") | ForEach-Object {
if (Test-Path "$OUTPUT_DIR/$_") { Write-Host "✅ $_" }
else { Write-Host "❌ MISSING: $_" }
}
Analysis quality matters. Bad: "Didn't work". Good: "Fix attempted to reset state in OnPageSelected, but this fires after layout measurement. The cached value was already used."
ALWAYS restore, even if fix failed.
pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore
🚨 Use EstablishBrokenBaseline.ps1 -Restore — not git checkout, git restore, or git reset (see Step 2 for why).
Provide structured output to the invoker:
## Try-Fix Result
**Approach:** [Brief description of what was tried]
**Files Changed:**
- `path/to/file.cs` (+X/-Y lines)
**Result:** ✅ PASS / ❌ FAIL
**Analysis:**
[Why it worked, or why it failed and what was learned]
**Diff:**
(paste `git diff` output here)
**This Attempt's Status:** Done/NeedsRetry
**Reasoning:** [Why this specific approach succeeded or failed]
Determining Status: Set Done when you've completed testing this approach (whether it passed or failed). Set NeedsRetry only if you hit a transient error (network timeout, flaky test) and want to retry the same approach.
| Situation | Action |
|---|---|
| Problem unclear | Report "insufficient context" - specify what's missing |
| Test command fails to run | Report build/setup error with details |
| Test times out | Report timeout, include partial output |
| Can't determine fix approach | Report "no viable approach identified" with reasoning |
| Git state unrecoverable | Run pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore (see Step 2/8) |
✅ Null/state checks - Guard against unexpected null or state ✅ Lifecycle timing - Move code to correct lifecycle event ✅ Cache invalidation - Reset stale cached values
❌ Massive refactors - Keep changes minimal ❌ Suppressing symptoms - Fix root cause, not symptoms ❌ Multiple unrelated changes - ONE focused fix per invocation
See references/example-invocation.md for a complete example with sample inputs.