skill-repair
Diagnose and fix failing or degraded skills automatically - systemic-first triage, per-category playbooks, and a verification plan
git clone --depth 1 https://github.com/aeonfun/aeon /tmp/skill-repair && cp -r /tmp/skill-repair/skills/skill-repair ~/.claude/skills/skill-repairSKILL.md
<!-- autoresearch: variation D — systemic-first triage + per-category playbooks + verification (folds A's regression hunter, B's structured PR + risk class + verdict, C's exit taxonomy + preflight + cooldown) -->
> **${var}** — Skill name to repair. If empty, runs systemic triage and picks the worst fixable target.
> **`${var}` modifiers**: prefix `dry-run:` to diagnose only without writing a PR (e.g. `dry-run:digest`).
Today is ${today}. Your task is to diagnose and repair the worst-impact failing or degraded skill — preferring a single shared fix over N per-skill patches when failures cluster.
## Phases
`PREFLIGHT → TRIAGE → DIAGNOSE → REPAIR → VERIFY → LOG`
Stop early at the appropriate exit code if any phase finds nothing actionable.
## Exit taxonomy
Pick exactly one before notifying.
| Code | Meaning |
|---|---|
| `REPAIR_OK_FIXED` | Per-skill fix applied, PR opened |
| `REPAIR_OK_SYSTEMIC` | Shared root cause across N skills — single shared fix or shared issue filed |
| `REPAIR_DIAGNOSED_NO_FIX` | Root cause known but requires operator action (e.g. missing secret, upstream API down). Issue updated, no PR |
| `REPAIR_NO_TARGETS` | All tracked skills healthy and no open fixable issues |
| `REPAIR_DRY_RUN` | `var=dry-run:NAME` — diagnostic only, no PR |
| `REPAIR_BLOCKED` | Preflight failed (gh auth, missing files) or cooldown active |
## 1. PREFLIGHT
Bail early with `REPAIR_BLOCKED` (and notify with the reason) if any of these fails:
- `gh auth status` succeeds.
- `memory/cron-state.json` exists and parses as JSON.
- `memory/issues/INDEX.md` exists. If absent, bootstrap a minimal one (Open + Resolved tables, no rows).
- `memory/state/skill-repair-history.json` exists. If absent, create `{}`.
**Cooldown / idempotency** (skip target with `REPAIR_BLOCKED` if any matches; don't loop on a fix that didn't take):
- The chosen target appears in `memory/state/skill-repair-history.json` with `last_repair_at` within 24h. (Operator can override by deleting the entry.)
- An open PR already exists matching `fix/skill-repair-{name}-*` — `gh pr list --state open --search "head:fix/skill-repair-{name}"`.
- More than 3 skill-repair PRs already opened in the current UTC day — rate-limit our own PRs.
If `${var}` starts with `dry-run:`, strip the prefix to get the target name and skip the cooldown.
## 2. TRIAGE
Identify the target. Two paths:
**Path A — `${var}` set explicitly:** repair that skill. Skip step 2's clustering.
**Path B — `${var}` empty (auto-select):**
1. Read `memory/issues/INDEX.md`. Extract open issues. Skip `permanent-limitation`.
2. Read `memory/cron-state.json`. Compute candidates where any of:
- `consecutive_failures >= 2`, OR
- `success_rate < 0.5` AND `total_runs >= 3`, OR
- `last_status == "failed"` AND `last_failed` within 48h, OR
- `last_quality_score <= 2` (degraded output even when "successful").
3. **Cluster by error signature.** Group candidates by normalized `last_error` (lowercase, strip timestamps/ids/digits) AND by issue `category`. If 2+ skills share a signature OR a non-trivial category (`api-change`, `rate-limit`, `missing-secret`, `sandbox-limitation`):
- This is **systemic**. Switch to systemic mode:
- File or update a single shared issue (`affected_skills: [list]`) instead of N per-skill issues.
- If the shared root cause is fixable in one place (e.g., a shared script under `scripts/`, a CLAUDE.md pattern, a shared config), open one PR addressing that. Otherwise emit `REPAIR_DIAGNOSED_NO_FIX` with the systemic finding.
- Exit with `REPAIR_OK_SYSTEMIC` after step 5.
4. **Pick worst single target.** Sort: critical issue > high issue > consecutive_failures desc > lowest success_rate > stalest `last_success`. Skip `permanent-limitation` and any target whose preflight cooldown blocks it. If nothing remains: `REPAIR_NO_TARGETS`.
## 3. DIAGNOSE
Build a diagnostic dossier for the target before touching any file. Sources are independent — each one's status feeds the source-status footer (`ok`/`empty`/`fail`).
a. **Skill file**: read `skills/{name}/SKILL.md`. Note frontmatter, declared data sources, env-var references.
b. **Cron-state entry**: extract `last_error`, `last_failed`, `last_success`, `success_rate`, `consecutive_failures`, `last_quality_score`.
c. **Regression hunter**: if `last_success` exists, run
```bash
git log --oneline --since="$LAST_SUCCESS" -- skills/{name}/SKILL.md aeon.yml scripts/
```
Any commit listed is a candidate regression source. If exactly one commit touched the skill file in this window, it is the prime suspect — record its SHA + subject in the dossier.
d. **Recent failed runs (last 5, not just 1)**:
```bash
gh run list --workflow=aeon.yml --limit 50 --json databaseId,name,conclusion,createdAt \
| jq -r '[.[] | select(.name | contains("{name}")) | select(.conclusion=="failure")] | .[0:5]'
```
For each, prefer `gh run view "$RUN_ID" --log-failed` (already filtered to failed steps) over the full log; fall back to `gh run view "$RUN_ID" --log` only if `--log-failed` returns nothing. Then:
```bash
gh api "repos/{owner}/{repo}/actions/runs/$RUN_ID/check-runs" \
| jq -r '.check_runs[].output.annotations[]? | "\(.path):\(.start_line) \(.annotation_level): \(.message)"'
```
Annotations give clean error rows; logs give context. Distinguish **consistent** (same signature 4-5/5 runs → likely deterministic bug, secret, API change) from **intermittent** (1-2/5 → rate limit, flaky upstream).
e. **Logs**: search last 3 days of `memory/logs/*.md` for `{name}` mentions. Surface any prior diagnoses.
f. **Quality history**: if `memory/skill-health/{name}.json` exists, note `avg_score` trend.
g. **Output expectations**: read the target skill's own `SKILL.md` (its Output / format section and `## Summary` contract) for the shape a good run must produce — required sections, a word floor, forbidden placeholders. A passing run that violates its own spec is `qualSet up and run an Aeon agent instance — get started from scratch, pick which skills to turn on or install more from packs, reschedule or change what runs, edit what an existing skill does, fix a skill that isn't firing, set the STRATEGY.md north star and soul/ voice, turn a coding-agent chat into a scheduled Aeon skill, and mine past coding-agent conversations for recurring work worth automating as a skill. Use when the user mentions Aeon, aeon.yml, an Aeon skill / instance / routine / pack, asks to schedule, enable, edit, or debug an agent that runs on a cron, or asks what of their repeated/manual work Aeon could take over.
Mention/keyword sweep on social platforms for [REPLACE: KEYWORDS] — trends, sentiment, top posts
5 concrete real-life actions, leverage-scored against open loops with specificity and anti-fluff gates
Static config-correctness linter for this instance - catches the silent-failure class (unquoted schedules, duplicate keys, unconfigured skills, mode typos, broken requires/MCP refs) that no run-based health skill can see. Notifies only on problems.
Pull framework updates from the upstream Aeon repo into this instance - 3-way merges canon's new commits into a PR, never clobbering operator config.
Write a publication-ready article in one of three angles - a trending long-form piece, a watched-repo thesis, or a project-through-a-lens essay. Optional Replicate hero image with --visual.
Automatically merge open PRs that have passing CI, no blocking reviews, and no conflicts
Two-mode aeon.yml workflow builder - analyze inspects URLs and emits a tiered, signal-verified skill-enablement plan plus an aeon.yml diff; enable flips slugs to enabled:true and opens a PR.