Verify repair loop
Skill event4u-app/agent-config/dist/agent-src/skills/verify-repair-loop
Universal AI Agent OS — audited skills, governance rules, replayable state. One contract, every host agent.
npx -y skills add event4u-app/agent-config --skill verify-repair-loopAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use to iterate a change until tests/quality checks pass — bounded run→revise→re-run gated by a numeric threshold, then a judge confirms. Triggers 'iterate to green', 'keep fixing until tests pass'.
SKILL.md
9.8 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
verify-repair-loop
Bounded generate → run → revise → re-run cycle; pass signal = the executed verdict (real test/quality output, scored vs a numeric threshold), escalated to a judge for qualitative confirmation only after the numeric gate passes (staged escalation). Loop is the conversation, not a process: no daemon, no persistent cross-session state. Use to drive a change to green when the verdict source is runtime execution, not a judge reading a diff.
When to use
- Change must converge against the project's test runner / quality tools; iterate until checks pass before review.
- Test/quality coverage is the authoritative signal (high coverage, actionable failures) — not subjective craft.
- Bounded auto-repair with a hard stop, not an open-ended fix loop.
Do NOT use when:
- Verdict is subjective craft (naming, architecture, style) or coverage
incomplete →
do-and-judgeinsubagent-orchestration(judge reads the diff, sovereign). - Only a one-shot multi-judge review of a finished diff →
/review-changes. - Verdict must come from a live app (Playwright vs running services) → deferred (see Scope); use test/quality verdicts until that trigger fires.
The Iron Law
THE NUMERIC VERDICT IS NEVER SOVEREIGN.
TESTS DECIDE WHEN TO ESCALATE — A JUDGE DECIDES WHETHER TO APPLY.
A REVISION THAT BREAKS A PREVIOUSLY-GREEN CHECK STOPS THE LOOP,
EVEN IF THE OVERALL SCORE ROSE.
GENERATOR NEVER APPROVES ITS OWN CHANGE.
A loop optimizing for pass_count ≥ N can game the metric — delete tests, skip
assertions, weaken checks — and still hit the threshold. The numeric gate only
decides when to escalate; a judge with veto confirms the change is real.
Procedure
1. Freeze the contract (spec fingerprint)
Before the first run, snapshot what "done" means:
- the task's acceptance criteria / requirement,
- the check set defining the verdict (test files + quality commands),
- a spec fingerprint = hash of (requirement text + check set).
Record the baseline green set — checks passing before any edit — so
regressions are detectable. Pick verdict commands per the project's
toolchain-resolver (PHP / JS-TS
/ Python / Go / Rust), not a hardcoded runner.
2. Set the gate
| Knob | Default | Meaning |
|---|---|---|
threshold | all targeted checks green | numeric pass bar, absolute (fraction of total), not "± N tests" |
allow_regressions | false | a revision breaking a baseline-green check stops the loop |
max_attempts | 3 | hard cap (test feedback is more actionable than diff critique → one more than do-and-judge's 2; bounded by autonomous-execution N=3) |
plateau_window | 3 | stop if the last window scores sit within tolerance |
tolerance | small absolute fraction | flake jitter that does not count as improvement |
3. The loop (multi-turn — the conversation IS the loop)
Each iteration is agent turns, never executing control-flow code:
- Generate / revise — smallest change toward the contract.
- Run — execute verdict commands; parse the structured result (green/total, which checks failed). One tool call, read in context.
- Score + regression check — compute the score; compare failures vs the
baseline green set.
- Regression (a baseline-green check now fails) → STOP, hand back with the regression named, even if the score rose. No whack-a-mole.
- Plateau (last
plateau_windowscores withintolerance) → STOP; surface suspected flakiness or a stuck point. Do not thrash. attempts == max_attempts→ STOP, hand back the best envelope.
- Numeric gate — score
< thresholdand attempts remain → back to step 1 (attempts++). Score≥ threshold, no regression → escalate (step 4).
4. Judge escalation (only after the numeric gate passes)
Dispatch the judge as a subagent with fresh context (the judge-* cluster via
subagent-orchestration) seeing only the
diff + executed results — never the generator's reasoning. This is the real
generator ≠ judge separation; single-agent persona-switching is theater.
- judge
apply→ DONE. - judge
revise→ back to step 3.1 (attempts++; bounded). - judge
reject→ STOP, hand back; the approach must change.
5. Mid-loop invalidation (user-interrupt-priority)
Re-check the spec fingerprint each iteration. If the user changes the requirement
mid-loop (a new instruction in the conversation), the fingerprint changes →
abort and hand back per
user-interrupt-priority. Never iterate
against a stale contract.
Scope — what runs, what is deferred
| Verify context | In scope | Why |
|---|---|---|
| Unit / integration tests | ✅ | fast, deterministic, sandboxed — runtime-free |
| Static quality (lint, type-check, format) | ✅ | fast, deterministic, no side effects (auto-fixable failures may bypass the revise step) |
| Live-app Playwright / E2E | ⛔ deferred | needs running services (DB, API) = a runtime; trigger = a UI-observable mission output + Playwright wired into a consumer CI |
State lives in the conversation, optionally mirrored to a re-read working file —
never a daemon or persistent cross-session store (honors
no-runtime-boundary).
Validation
Before finalizing, confirm:
- The numeric gate escalated to a judge — it did not apply on its own.
- No baseline-green check regressed (or the loop stopped and said so).
- The loop stopped at
max_attempts, a plateau, or a judgeapply— never ran unbounded. - The judge saw only the diff + results, dispatched in fresh context.
- No daemon / persistent runtime introduced.
Output format
verify-repair-loop
Contract: <one-line requirement> · threshold <X> · allow_regressions false
Attempts: <k>/<max> scores: [s1, s2, …] stop: threshold|plateau|cap|regression|reject
Verdict: DONE | DONE_WITH_CONCERNS | BLOCKED
Judge: <judge skill> → apply|revise|reject
Evidence: <green/total> · regressions: none | <named checks>
Required fields (ordered):
- Contract — frozen requirement + threshold +
allow_regressions. - Attempts —
k/max, score history, exact stop reason (threshold/plateau/cap/regression/reject). - Verdict —
DONE,DONE_WITH_CONCERNS, orBLOCKED. - Judge — dispatched judge skill + its
apply/revise/rejectverdict (omit only when the loop stopped before escalation). - Evidence — final
green/totaland any regressed checks by name.
Examples
Good — staged, bounded, judge confirms:
iter1 84/100 (<90) → revise
iter2 93/100 (≥90, no regression) → escalate → judge apply → DONE
Bad — numeric verdict treated as sovereign (rejected by the Iron Law):
iter1 91/100 ≥ threshold → "PASS, done" ✗ no judge escalation; metric may be gamed
iter2 fixes A, breaks B, 92% → "PASS" ✗ regression ignored
Gotcha
- Metric gaming — agent "passes" by deleting a failing test or weakening an
assertion. The numeric gate can't catch this; the fresh-context judge is the
safeguard. A diff that removes checks is a
reject, not apass. - Flake mistaken for a plateau — one non-deterministic test flips the score and the window-comparison reads "no improvement". Re-run the suspected check before declaring a plateau; surface flakiness instead of thrashing.
- Score rose, but a regression hid inside it — fixing 6 checks while breaking 2 still raises the total. Without the regression guard the loop ships a regression. Diff failures against the baseline green set, not just the aggregate.
- Persona-switch theater — asking the same agent to "now judge what you wrote" is not separation. Dispatch the judge as a fresh-context subagent that never saw the generator's reasoning.
- Stale contract — iterating against a requirement the user changed mid-loop. Re-check the spec fingerprint each turn; a change aborts.
Do NOT
- NEVER let the numeric score apply a change without judge confirmation.
- NEVER continue past a regression because the overall score improved.
- NEVER run the live-app Playwright path here — it is deferred (needs a runtime).
- NEVER judge with the generator's own context — dispatch a fresh-context judge.
- NEVER loop past
max_attemptsor a detected plateau.
See also
subagent-orchestration—do-and-judge(judge-sovereign, diff-read) is the sibling; this skill is test-verdict-gated./review-changes— one-shot multi-judge review; wires this loop as an opt-in step.playwright-testing,quality-tools— verdict sources.autonomous-execution— the N=3 cap.no-runtime-boundary— the runtime-free constraint this loop honors.- Optional impact pre-step (when a code-graph is present, ADR-124): run
code_graph affected --since <ref>to scope which symbols a change touches before choosing verdict sources — cited, not duplicated; the loop itself is unchanged when no graph exists.
What ships with it: 2 files
2.3 KB alongside SKILL.md
evals/
- output-schema.yml667 B
- triggers.json1.7 KB