--- 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 = "" # 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//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. 4. **Write findings to `$OUTPUT_DIR/reviewer-findings.json`.** Always write the file, even when there are zero findings. Use the same JSON format as the `@maui-expert-reviewer` agent (matches the GitHub Pull Request Review API): ```powershell # No findings β€” clean self-review (or no diff to review): '[]' | Set-Content "$OUTPUT_DIR/reviewer-findings.json" # With findings β€” JSON array of {path, line, body}: @' [ { "path": "src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs", "line": 42, "body": "**[major] Layout Measure-Arrange** β€” Content measured with unconstrained height but arranged with bounded height. Concrete scenario: ScrollView inside a Grid with Star row height." } ] '@ | Set-Content "$OUTPUT_DIR/reviewer-findings.json" ``` Each entry has exactly 3 fields: - **`path`** (string) β€” file relative to repo root, must be a file present in your diff - **`line`** (integer β‰₯ 1) β€” line number on the changed (right) side of the diff. The line MUST appear in your diff β€” picking an unchanged line is wrong. Use `1` only as a fallback for file-level concerns where no single line captures the issue (e.g., missing import, structural concern). - **`body`** (string) β€” format `**[severity] Dimension** β€” description`. Severity is one of `critical`/`major`/`moderate`/`minor`. 5. **Validate the JSON parses and capture the count:** ```powershell try { $findings = @(Get-Content "$OUTPUT_DIR/reviewer-findings.json" -Raw | ConvertFrom-Json) $findingsCount = $findings.Count Write-Host "βœ… reviewer-findings.json: $findingsCount findings" } catch { Write-Host "❌ reviewer-findings.json is invalid JSON: $_" throw } # Snapshot the diff that was reviewed β€” Step 7.5 uses this to detect whether the test loop mutated code. # Use Set-Content -Value with Out-String so the file is created even when the diff is empty # (a bare `git diff | Set-Content` does NOT create the file when the pipe is empty). Set-Content -Path "$OUTPUT_DIR/reviewer-findings.diff" -Value (git diff | Out-String) -NoNewline ``` **Remember `$findingsCount`** β€” you will report it as `findings_count` in Step 10 and summarize it in `analysis.md` (Step 8). 6. **Fix critical/major findings BEFORE testing:** - If there are any `[critical]` or `[major]` findings β†’ apply fixes for them in a single batch and rewrite `reviewer-findings.json` to reflect the new diff. - All `[moderate]` and `[minor]` findings β†’ note in `analysis.md` (Step 8); do NOT iterate. - Only ONE correction round. Then proceed to Step 7 (Test). **Threshold guidance.** Only record findings with a concrete failing scenario. Stylistic preferences and bikeshedding (see the **`## What NOT to Flag`** table in `maui-expert-reviewer.md`) are not findings. An empty `[]` is the correct output for a clean fix β€” do not invent findings to fill the file. > **Why before testing?** Self-review catches design flaws (wrong null check, missing platform guard, thread safety issue) before you spend 5-15 minutes on a build+test cycle. It also runs when context is lightest β€” before test output floods the context window. ### Step 7: Test and Iterate (MANDATORY) 🚨 **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 -TestFilter ""` | | DeviceTest | `pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project -Platform -TestFilter ""` | | UnitTest | `dotnet test --filter ""` | ```powershell # Capture output to test-output.log while also displaying it # Example for UI tests: pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform -TestFilter "" *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/test-output.log" # Example for device tests: pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project -Platform -TestFilter "" *>&1 | Tee-Object -FilePath "$OUTPUT_DIR/test-output.log" ``` **Testing Loop (Iterate until SUCCESS or exhausted):** 1. **Run the test command** - It will build, deploy, and test automatically 2. **Check the result:** - βœ… **Tests PASS** β†’ Move to Step 7.5 (Refresh self-review if needed) - ❌ **Compile errors** β†’ Fix compilation issues (see below), go to step 1 - ❌ **Tests FAIL (runtime)** β†’ Analyze failure, fix code, go to step 1 3. **Maximum 3 iterations** - If still failing after 3 attempts, analyze if approach is fundamentally flawed 4. **Document why** - If exhausted, explain what you learned and why the approach won't work **Behavioral constraints:** - ⚠️ **NEVER blame "test infrastructure"** - assume YOUR fix has a bug - Compile errors mean "work harder" - not "give up" - DO NOT manually build - always rerun the test command script See [references/compile-errors.md](references/compile-errors.md) for error patterns and iteration examples. ### Step 7.5: Refresh Self-Review If Code Changed (MANDATORY) 🚨 **The test loop in Step 7 may modify code (compile-error fixes, runtime-error fixes). When that happens, the `reviewer-findings.json` written in Step 6 describes a stale diff β€” not the diff that will be captured in Step 8 and shipped to the reviewer.** This step re-runs the self-review against the *final* diff so the recorded findings always correspond to the actual fix. **Procedure:** 1. **Detect drift.** Compare the current working-tree diff against the diff Step 6 reviewed. ```powershell # Force both sides to a single string. `git diff` assigned to a variable is a string[] # (one element per line); `-ne` between an array and a scalar is element-wise filtering, # not equality. Both must be normalized to the same shape before comparison. # # Also: `Get-Content -Raw` on a 0-byte file returns $null, not "". The Step 6 snapshot # creates a 0-byte file when the diff is empty (the documented Blocked-with-no-diff path), # so coalesce $null to "" via `?? ''` to avoid a false-positive "" -ne $null drift detection. $currentDiff = (git diff | Out-String) $reviewedDiff = if (Test-Path "$OUTPUT_DIR/reviewer-findings.diff") { (Get-Content "$OUTPUT_DIR/reviewer-findings.diff" -Raw) ?? '' } else { '' } $diffChanged = ($currentDiff -ne $reviewedDiff) if (-not $diffChanged) { Write-Host "βœ… Diff unchanged since Step 6 β€” self-review still current. Skip sub-steps 2 and 3." } else { Write-Host "πŸ” Code changed during Step 7 β€” refreshing self-review against final diff..." } ``` 2. **If `$diffChanged` is `$true`, re-do the Step 6 self-review against the new diff.** This is YOU walking the rules again β€” it is *not* something the script does. Repeat the same procedure from Step 6: 1. **Re-list changed files:** `git diff --name-only HEAD` 2. **Re-walk the rules** in `.github/agents/maui-expert-reviewer.md` β€” every Overarching Principle, the always-active dimensions, and any routed dimensions whose file paths now match. 3. **Rewrite `$OUTPUT_DIR/reviewer-findings.json`** with the new findings (or `'[]'` if clean). The file MUST be overwritten β€” appending or leaving the old content is a bug. Use the same JSON schema documented in Step 6. 3. **Re-snapshot and re-validate.** Only after rewriting the JSON in sub-step 2, run: ```powershell # Re-snapshot the diff (matches Step 6's snapshot logic β€” works for empty diffs too). Set-Content -Path "$OUTPUT_DIR/reviewer-findings.diff" -Value (git diff | Out-String) -NoNewline # Re-validate the JSON parses and capture the new count. try { $findings = @(Get-Content "$OUTPUT_DIR/reviewer-findings.json" -Raw | ConvertFrom-Json) $findingsCount = $findings.Count Write-Host "βœ… reviewer-findings.json refreshed: $findingsCount findings" } catch { Write-Host "❌ reviewer-findings.json is invalid JSON: $_" throw } ``` > **Why no programmatic "did you actually rewrite the JSON" check?** A SHA256 hash sentinel rejects the legitimate byte-identical case (e.g., `[]` β†’ `[]` after a small compile fix that introduces no new violations), and that case is common. The procedural enforcement is sub-step 2's explicit numbered list above, plus the example-invocation chain that walks the dimensions explicitly. If sub-step 2 is skipped, the JSON validates but ships a stale review β€” accept that risk in exchange for not blocking valid clean fixes. **Severity handling is the same as Step 6.** If the refresh surfaces new `[critical]` or `[major]` findings, you may apply ONE more fix batch and re-run the test loop, then re-refresh. Do not loop indefinitely β€” if a fix introduces critical findings on the third pass, mark the attempt `Blocked` and explain in `analysis.md`. ### Step 8: Capture Artifacts (MANDATORY) **Before reverting, save ALL required files to `$OUTPUT_DIR`:** ```powershell # 1. Save result (MUST be exactly "Pass", "Fail", or "Blocked") "Pass" | Set-Content "$OUTPUT_DIR/result.txt" # or "Fail" # 2. Save the diff (use Set-Content -Value with Out-String so the file is created # even when the diff is empty β€” a bare `git diff | Set-Content` does not create # the file when the pipe is empty, which would fail the artifact gate.) Set-Content -Path "$OUTPUT_DIR/fix.diff" -Value (git diff | Out-String) -NoNewline # 3. Save test output (should already exist from Step 7) # Copy-Item "path/to/test-output.log" "$OUTPUT_DIR/test-output.log" # 4. reviewer-findings.json should already exist from Step 6 (and may have been refreshed by Step 7.5) # 4b. reviewer-findings.diff snapshot (used by Step 7.5 to detect drift) # 5. Save analysis (include a one-line summary of self-review findings) @" ## Analysis **Result:** Pass/Fail/Blocked **What happened:** [Description of test results] **Why it worked/failed:** [Root cause analysis] **Self-review:** [N findings: brief summary of each, or "clean β€” no findings"] **Insights:** [What was learned that could help future attempts] "@ | Set-Content "$OUTPUT_DIR/analysis.md" ``` **Verify all required files exist (this is the enforcement gate for Steps 6 and 7 β€” primarily `reviewer-findings.json` from Step 6, refreshed by Step 7.5 if needed):** 🚨 **The artifact check below MUST be wrapped so that Step 9 (Restore) ALWAYS runs even if the check fails.** A failed gate that skips restore would leave the worktree dirty and corrupt the next sequential try-fix attempt. ```powershell # Run the file-existence check, but DEFER any throw until after Step 9 has restored the worktree. $missing = @() @("baseline.log", "approach.md", "result.txt", "fix.diff", "analysis.md", "test-output.log", "reviewer-findings.json", "reviewer-findings.diff") | ForEach-Object { if (Test-Path "$OUTPUT_DIR/$_") { Write-Host "βœ… $_" } else { Write-Host "❌ MISSING: $_" $missing += $_ } } # Record the gate result for use after Step 9 β€” DO NOT throw here. if ($missing.Count -gt 0) { $gateFailureMessage = "Required artifacts missing: $($missing -join ', '). If 'reviewer-findings.json' is missing, Step 6 (Expert Self-Review) was not performed (or Step 7.5 did not refresh it after the test loop) β€” it is mandatory and must contain at least '[]' that reflects the final diff." Write-Host "⚠️ ARTIFACT GATE FAILED β€” proceeding to Step 9 restore before reporting failure." Write-Host $gateFailureMessage "Blocked" | Set-Content "$OUTPUT_DIR/result.txt" -Force } else { $gateFailureMessage = $null } ``` **If `$gateFailureMessage` was set:** Step 9 still runs (do NOT skip it). After Step 9 restores the target files, surface the failure in Step 10's report β€” set `result.txt` to `Blocked` (already done above) and explain in `analysis.md` which artifact was missing. The next sequential attempt then starts from the same restored baseline state, including any pre-existing untracked harness inputs. **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." ### Step 9: Restore Working Directory (MANDATORY β€” runs even if Step 8 gate failed) **ALWAYS restore, even if fix failed or Step 8 detected missing artifacts.** Skipping restore corrupts the next sequential try-fix attempt. ```bash pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore ``` If restore continues in the background, wait for its matching `shellId` with `read_bash` until it completes. When Step 2 created `.github/.baseline-state.json`, do not report the attempt or end the session until restore confirms `Restored True`. If Step 2 already reported `Blocked` before changing any files and verified that baseline state was never created because all fix files were new or no fix files were detected, the expected completion is `No baseline state found` with `Restored False`; accept that result only for those verified no-state paths and only when no attempt edits were made. 🚨 Use `EstablishBrokenBaseline.ps1 -Restore` β€” not `git checkout`, `git restore`, or `git reset` (see Step 2 for why). After restoration, leave every pre-existing untracked path unchanged. In particular, an evaluator-loaded `try-fix/` directory may remain visible in `git status --short`; do not delete it. Judge restoration by `Restored True` and by the absence of attempt-created changes to the allowed target files, not by forcing all untracked harness inputs out of the workspace. ### Step 10: Report Results Provide structured output to the invoker: ```markdown ## Try-Fix Result **Approach:** [Brief description of what was tried] **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 avoided that failure] **Files Changed:** - `path/to/file.cs` (+X/-Y lines) **Result:** βœ… PASS / ❌ FAIL **Self-Review:** N findings (X critical, Y major, Z moderate/minor) β€” see `reviewer-findings.json` **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] ``` The two approach-comparison fields must be self-contained prose, not labels or fragments. When prior attempts share a root cause, explicitly name that shared failure mechanism. Then connect the new mechanism to the failure with a causal explanation (for example, β€œbecause X now happens after Y, Z is available directly, so the failing fallback is never consulted”). Do not rely on the contents of `approach.md` or `analysis.md` being visible to the invoker. **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. ## Error Handling | 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/9) | --- ## Guidelines for Proposing Fixes ### Good Fix Approaches βœ… **Null/state checks** - Guard against unexpected null or state βœ… **Lifecycle timing** - Move code to correct lifecycle event βœ… **Cache invalidation** - Reset stale cached values ### Approaches to Avoid ❌ **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](references/example-invocation.md) for a complete example with sample inputs.