Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Test-Driven Repair — given a failing test, spawn a bounded headless `claude -p` (Read/Edit/Bash only) that makes the test pass without modifying it. Modeled on agent-harness-generator's ADR-175 Test-Driven Repair mode. Bounded cost via --max-budget-usd, bounded capability via --allowedTools. Closes the loop the TDD plugins didn't — we generate tests, this fixes the code to satisfy them.
.claude/skills/ruvnet-tdd-repair/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 21% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -5% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 91% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 46% | 0% |
Surfaces the Test-Driven Repair loop as a ruflo skill. Use when you have a failing test and want the source-under-test fixed automatically, with the test's pass/fail as the verification gate (no LLM-as-judge).
tdd-workflow skill), then run tdd-repair to drive the green.--no-test-oracle) is scoped for a follow-up ADR — needs MCTS over repro generation. For now, write a failing test first.claude -p runs with --allowedTools Read,Edit,Bash — no MCP, no network, no arbitrary file writes — but Bash can still touch the filesystem. Don't point this at code you wouldn't git checkout . after.Implementation: scripts/tdd-repair/tdd-repair.mjs.
test-already-passes). Repairing a green test is either a no-op or a --test-command typo.claude -p with a focused prompt:--allowedTools Read,Edit,Bash restricts capability. --max-budget-usd caps cost per attempt. --permission-mode acceptEdits auto-accepts file edits within the allowed set.success: true + per-attempt usage. If red after --max-attempts: emit success: false + receipts. Either way, the workspace is left as claude -p modified it (caller can git diff to review).json{ "success": true, "data": { "repaired": true, "attemptsTaken": 1, "mode": "test-driven", "before": { "passed": false, "exitCode": 1 }, "after": { "passed": true, "exitCode": 0, "durationMs": 4321 }, "attempts": [ { "attempt": 1, "claude": { "ok": true, "durationMs": 38421, "usage": { "cost_usd": 0.0234 } }, "verify": { "passed": true } } ], "totalCostUsd": 0.0234, "budgetUsd": 5.0, "budgetExhausted": false, "shape": { "repo": "...", "test": "...", "testCommand": "...", "maxAttempts": 1, "model": "haiku" } } }
| Code | Meaning | |---|---| | 0 | Test green after repair (success) | | 1 | Test still red after --max-attempts | | 2 | Config error (test file missing, test already passes, --no-test-oracle unsupported, etc.) | | 3 | Claude CLI exited non-zero (infrastructure failure) | | 99 | Reserved for safety tripwire (per ADR-153) |
| Layer | Mechanism | |---|---| | Cost cap | --max-budget-usd default $5, divided across --max-attempts. Hard ceiling — claude exits when reached. | | Capability cap | --allowedTools Read,Edit,Bash — no MCP, no network, no arbitrary writes. | | Scope cap | Prompt forbids modifying the test or adding dependencies. | | Confirmation gate | --confirm REQUIRED — without it, returns dry-run plan (mirrors harness-evolve / harness-mint convention). | | Hard timeout | 15 min total wall-clock; per-attempt budget of timeoutMs / maxAttempts. | | Pre-flight | Refuses to run if the test already passes (catches --test-command typos). |
Modeled on the Test-Driven Repair mode from agent-harness-generator/packages/darwin-mode ADR-175. Key design difference: instead of wrapping metaharness-darwin evolve (population-based search), we drive a single claude -p invocation. Rationale:
claude -p is already in our stack — no new optional dep--session-id if iteration is neededConformant mode (no test, write own repro via MCTS) is deferred to a future ADR.
bash# Smoke / dry-run (no --confirm yet) node plugins/ruflo-testgen/scripts/tdd-repair/tdd-repair.mjs \ --repo /path/to/myrepo \ --test tests/auth.test.ts \ --test-command "npx vitest run tests/auth.test.ts" # Actually repair (Haiku tier, $5 budget, 1 attempt) node plugins/ruflo-testgen/scripts/tdd-repair/tdd-repair.mjs \ --repo /path/to/myrepo \ --test tests/auth.test.ts \ --test-command "npx vitest run tests/auth.test.ts" \ --confirm # Bigger model + more attempts for harder bugs node plugins/ruflo-testgen/scripts/tdd-repair/tdd-repair.mjs \ --repo . --test tests/regression-2456.test.ts \ --test-command "npm test -- tests/regression-2456.test.ts" \ --model sonnet --max-attempts 3 --budget 15.00 \ --confirm
| Tier | Model | Per-attempt typical | Use when | |---|---|---:|---| | 1 | Haiku | $0.02 – $0.20 | First try — most "make red green" bugs are tactical | | 2 | Sonnet | $0.30 – $2.00 | Haiku failed, or the bug has multi-file scope | | 3 | Opus | $1.50 – $8.00 | Sonnet failed — architectural reasoning required (rarely worth it for a single failing test) |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 5,307 | 5,004 | -6% | 1 | 1 | 0% | 432 | 2,019 | +367% | 0 | 0 | — |
case-02 | fail→fail | 12,958 | 20,433 | +58% | 1 | 1 | 0% | 259 | 2,015 | +678% | 0 | 0 | — |
case-03 | fail→fail | 4,905 | 6,101 | +24% | 1 | 1 | 0% | 475 | 2,173 | +357% | 0 | 0 | — |
case-04 | fail→pass | 10,726 | 1,883 | -82% | 1 | 1 | 0% | 1,733 | 2,094 | +21% | 0 | 0 | — |
case-05 | fail→pass | 8,781 | 3,986 | -55% | 1 | 1 | 0% | 1,359 | 1,960 | +44% | 0 | 0 | — |
case-06 | fail→pass | 12,018 | 1,446 | -88% | 1 | 1 | 0% | 2,088 | 1,978 | -5% | 0 | 0 | — |
case-07 | pass→pass | 5,670 | 1,416 | -75% | 1 | 1 | 0% | 908 | 1,992 | +119% | 0 | 0 | — |
case-08 | pass→pass | 11,733 | 2,265 | -81% | 1 | 1 | 0% | 1,942 | 2,139 | +10% | 0 | 0 | — |
case-09 | fail→pass | 17,268 | 1,340 | -92% | 1 | 1 | 0% | 982 | 1,875 | +91% | 0 | 0 | — |
case-10 | pass→pass | 12,042 | 2,424 | -80% | 1 | 1 | 0% | 2,097 | 2,145 | +2% | 0 | 0 | — |
case-11 | pass→pass | 6,074 | 1,760 | -71% | 1 | 1 | 0% | 1,049 | 2,062 | +97% | 0 | 0 | — |
case-12 | pass→pass | 8,093 | 2,820 | -65% | 1 | 1 | 0% | 1,374 | 2,270 | +65% | 0 | 0 | — |
case-13 | fail→pass | 8,946 | 3,097 | -65% | 1 | 1 | 0% | 1,550 | 2,265 | +46% | 0 | 0 | — |
case-14 | pass→pass | 6,410 | 1,567 | -76% | 1 | 1 | 0% | 974 | 1,968 | +102% | 0 | 0 | — |
case-15 | pass→pass | 5,888 | 1,701 | -71% | 1 | 1 | 0% | 956 | 1,952 | +104% | 0 | 0 | — |
case-16 | fail→pass | 6,632 | 2,526 | -62% | 1 | 1 | 0% | 1,165 | 2,260 | +94% | 0 | 0 | — |
case-22 | pass→pass | 9,802 | 6,709 | -32% | 1 | 1 | 0% | 1,803 | 2,872 | +59% | 0 | 0 | — |
case-17 | fail→pass | 14,072 | 3,273 | -77% | 1 | 1 | 0% | 2,763 | 2,347 | -15% | 0 | 0 | — |
case-18 | pass→pass | 10,813 | 4,327 | -60% | 1 | 1 | 0% | 1,696 | 2,489 | +47% | 0 | 0 | — |
case-19 | fail→pass | 5,035 | 1,502 | -70% | 1 | 1 | 0% | 916 | 1,940 | +112% | 0 | 0 | — |
case-20 | pass→pass | 13,886 | 5,818 | -58% | 1 | 1 | 0% | 2,299 | 2,763 | +20% | 0 | 0 | — |
case-21 | fail→pass | 11,053 | 9,068 | -18% | 1 | 1 | 0% | 1,913 | 2,493 | +30% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 18 counted toward the lift figure. The other 4 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 18 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.