Error Fixer Loop
Every fixed error must reduce the chance of the same error returning. If the loop ends at the patch, it failed — even if the patch worked.
Recursive skill: it closes the cycle between execution, verification, and harness improvement. Each run produces evidence (error found, decision made, test run, rule created, harness adjusted) and leaves the system harder to break in the same way.
Reference pattern: Como Criar uma Skill Recursiva.
Trigger
Load this skill when ANY of these is true:
- A
bash/shelltool call returns output matching a known build/test/typecheck error pattern (seehooks/— they auto-inject a reminder). - The user says: "investigate this error", "fix this build", "test failed", "typecheck broken", "error keeps coming back".
- You are about to conclude a fix and have not yet written a persistent rule.
Do not load for:
- Transient network/permission errors (one-off, not repeatable).
- Errors in code owned by external vendors (no write access).
- Pure refactors with no failing signal (use
code-smellorarchitecture-deepenerinstead).
Protocol (non-negotiable)
Follow the steps in order. Skipping steps is the exact failure this skill prevents.
1. Capture the event
- Paste the exact command that failed.
- Paste the exact error output (trimmed to the relevant 50 lines).
- Note the working directory and exit code.
2. Declare the root cause in one sentence
Format: <Component> fails because <specific reason>, triggered by <minimal repro>.
If you cannot write this sentence yet, you are not at root cause — go back to step 1 with a tighter repro (see bug-diagnostics for repro-building techniques).
3. Classify the failure
Pick exactly one primary class. This decides where the fix lives.
| Class | Symptom | Where the fix belongs |
|---|---|---|
procedure |
Skill/agent didn't say to run the check | this SKILL.md or the calling skill |
missing-rule |
Project convention violated repeatedly | docs/rules/<topic>.md or AGENTS.md |
missing-test |
Bug escaped because no seam | test suite (add regression test) |
permission |
Tool denied, sandbox blocked, path forbidden | harness policy (~/.config/opencode/permission.json, Claude settings) |
observability |
No log, no checkpoint, no evidence | logging/checkpoint layer |
documentation |
Agent followed stale doc | doc file referenced by agent |
4. Apply the minimal fix
- Touch only what is load-bearing for the error.
- No drive-by improvements. No "while I'm here" refactors.
- Match existing style.
5. Run the relevant verification
- If a test exists: run it.
- If no test exists and the bug is repeatable: write a failing test first, then fix, then watch it pass.
- Always run
lintandtypecheckfor TS/JS projects (tsc --noEmit,biome check,eslint). - Paste the verification output in the final report.
6. Persist the rule
If the failure is repeatable (same class can appear again), write a rule. Use this decision tree:
Is it specific to THIS project?
├─ yes → docs/rules/<topic>.md in the project, link from AGENTS.md
└─ no → could other projects hit it?
├─ yes → this SKILL.md (anti-patterns section) or a new global rule
└─ no → record in the final report only; do NOT write a rule
Rule format (one line, operational, verifiable):
- **<Rule name>**: <imperative sentence>. Verify with: <command or check>.
Good: Never use as anyto silence a TS error without a// justified: comment. Verify with: grep -rn "as any" src/ | grep -v justified.
Bad: Be careful with types. (not operational, not verifiable)
7. Update the harness index
- If you wrote a rule in
docs/rules/, link it fromAGENTS.mdunder the relevant section. - If you updated this
SKILL.md, bump the version inplugin.jsonand note the change in the audit.
8. Generate the fix-prompt artifact
Write a dynamic fix-prompt file so the fix can be replayed, delegated, or audited later — even in another session or harness.
- Location:
.error-fixer-loop/<YYYYMMDD-HHMMSS>-<short-slug>.md(create the folder if missing; add it to.gitignoreif the project doesn't want it versioned). - Template: use
templates/fix-prompt.mdfrom this plugin. - Format: the file MUST follow the
senior-prompt-engineeroutput shape — Role/Context, Task, Inputs/files, Constraints, Plan with→ verify:per step, Output contract, Feedback DO, Feedback DO NOT, and a closingEXEC-MAP v1fenced block. - Slug: 3–6 lowercase words describing the error class (e.g.
ts2322-string-to-number,jest-module-not-found). - Fill placeholders with real values from steps 1–7. Never ship a template with
<...>still in it.
This artifact is what makes the loop recursive across sessions: the next agent (or the same agent next week) can pick up the file and execute the fix without re-doing the investigation.
9. Final audit (mandatory)
Produce a short report answering ALL of:
- What was the failure (one sentence)?
- What was the root cause (one sentence)?
- What class (from step 3)?
- What changed (file:line list)?
- What verification ran (command + result)?
- What rule was persisted (file + one-line rule)?
- What fix-prompt was generated (path)?
- What risk remains?
Without the audit AND the fix-prompt, the loop is not closed.
Escopo de escrita (write scope)
This skill MAY propose or edit:
- This
SKILL.md(anti-patterns, protocol refinements). - Project rule files:
docs/rules/*.md,docs/ai/rules/*.md,AGENTS.md,CLAUDE.md. - Test files that reproduce the original error.
- Evals in this plugin (
evals.json). - Fix-prompt artifacts under
.error-fixer-loop/(always allowed; never requires confirmation).
This skill MUST NOT:
- Rewrite unrelated rules or remove guardrails.
- Change security/permission policy without explicit user confirmation.
- Mask a failing test to make verification pass.
- Delete a pre-existing failing test without documenting why.
- Use
as any,@ts-ignore,eslint-disableor equivalent to silence an error without an inline// justified: <reason>comment and a rule entry.
Anti-patterns (hard no)
- ❌ Concluding with "fixed" but no test run.
- ❌ Concluding without generating the fix-prompt artifact in
.error-fixer-loop/. - ❌ Shipping a fix-prompt with unfilled
<placeholders>. - ❌ Adding a rule based on personal preference (no evidence).
- ❌ Widening scope because "we might need it later".
- ❌ Removing a guardrail to reach "done" faster.
- ❌ Accepting a green test that does not cover the original failure.
- ❌ Writing a rule longer than one operational sentence.
- ❌ Updating the skill when the learning belongs to the project (and vice-versa).
Recursive improvement criteria
Update this SKILL.md only when ALL are true:
- The current protocol allowed a repeatable failure.
- The new rule is short and generalizable across projects.
- The change reduces future ambiguity.
- There is verification or evidence supporting it.
Update a project rule file when the learning is project-specific (e.g., "in this repo, blog posts need both index.md and index-pt-br.md").
Create an eval (evals.json) when the failure can be simulated (e.g., "agent concludes without running tests", "agent uses as any").
Hook integration
Three hooks auto-detect build/test errors in bash output and inject a reminder to run this loop:
- Claude Code:
hooks/error-fixer-loop-hook.sh— register asPostToolUseonBash. Plain-text output; Claude Code only. - Codex:
hooks/error-fixer-loop-codex.py— register asPostToolUseonBashin~/.codex/hooks.json. Prints nothing when clean, validhookSpecificOutputJSON on error. Never register the.shhook in Codex — Codex rejects plain-text hook output withhook returned invalid post-tool-use JSON output. - OpenCode:
hooks/error-fixer-loop.ts— plugin listening ontool.execute.after.
All are passive: they only emit a reminder. They never block, never mutate the tool result, never auto-run the fix.
Detected patterns (extend via ERROR_PATTERNS in the TS hook or the regex in the shell hook):
- TypeScript:
error TS\d+ - Module resolution:
Cannot find module,Module not found:,Unable to find a specification for - Build:
BUILD FAILED,GRADLE.*FAILED,npm ERR!,pod install.*fail - Tests:
Test Suites:.*[1-9]\d* failed,Tests:.*[1-9]\d* failed,jest.*FAIL - iOS/RN:
NitroModules.*not found - Python:
ModuleNotFoundError,ImportError,AssertionError,FAILED tests/ - Go:
FAIL\s+\S+,undefined:,cannot find package - Rust:
error\[E\d+\],panicked at - Java/Kotlin:
BUILD FAILURE,Compilation failure,> Task .* FAILED
Add new patterns only when you have seen them fire in the wild — not speculatively.
Layered feedback model
Do not pile every learning into this file. Four layers:
- Execution — the current task (tools, commands, files).
- Verification — tests, typecheck, lint, evals.
- Operational memory —
docs/rules/,AGENTS.md, thisSKILL.md. - Harness evolution — new tools, permission changes, new evals, dispatch tweaks.
Layer 4 is the most sensitive. Changes there must be small, verified, and reversible.
References
- Article: https://lemon.dev.br/pt/blog/skill-recursiva-feedback-loop-harness
- Legacy hook:
~/.claude/hooks/error-fix-loop-hook.sh(replaced byhooks/error-fixer-loop-hook.sh) - Companion skill:
bug-diagnostics(deep repro/hypothesis work when step 2 stalls) - Harness rules:
~/.config/opencode/AGENTS.md(global), projectAGENTS.md(local)