test-first-fix
Skill0 starsChanged 25 days agoMITView on GitHub
Use when fixing a bug, a failing test, or a reproducible defect in code. Turns a report into a minimal failing test, proves the failure reason, applies the smallest fix, and verifies with the full relevant suite. Also use for flaky tests and regressions after a dependency or model-driven change.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- TrueImmortal82/open-code-skillstheir own version, first seen Nov 8, 2026
- ceccopierangiolieugenio/pyTermTktheir own version, first seen Oct 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- ceccopierangiolieugenio/pyTermTk★ 921same name
- TrueImmortal82/open-code-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository18 other files it gives its agents.
- docs/agents.mdAGENTS.md
- agent-skill-authorSkill
- api-contract-reviewSkill
- codex-cli-workflowsSkill
- codex-plugin-authorSkill
- context-budgetSkill
- dependency-auditSkill
- docs-writerSkill
- git-recoverySkill
- incident-postmortemSkill
- mcp-server-builderSkill
- performance-profileSkill
- pr-reviewerSkill
- release-engineerSkill
- repo-onboardingSkill
- skill-security-reviewSkill
- sql-migration-reviewSkill
- terminal-debuggerSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
30 rules. About 0 are common, 30 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈30
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 22
Use this skill when:
- Distinctive: line 30
Do not use this skill for pure refactors with existing coverage.
- Distinctive: line 36
Write down, before touching code:
- Distinctive: line 50
If the report cannot be reproduced, stop and ask for the missing input.
- Distinctive: line 54
Remove everything that is not required.
- Distinctive: line 66
Add the test at the lowest level that still exercises the bug.
- Distinctive: line 88
Read the assertion output.
- Distinctive: line 100
If you have more than one hypothesis, rank them and test the cheapest first.
- Distinctive: line 106
Run the single test:
- Distinctive: line 121
Run the tests that cover direct callers.
- Distinctive: line 122
Run the full suite once.
- Distinctive: line 123
Run the reproduction from step 1, not only the test.
- Distinctive: line 124
If the bug involved time, run with a fixed clock or a different time zone.
- Distinctive: line 125
If the bug involved concurrency, run the test repeatedly.
- Distinctive: line 126
If the bug involved a browser, check the real browser, not only the unit test.
- Distinctive: line 130
Add a regression test that is specific enough to fail if the fix is reverted.
- Distinctive: line 132
Update the changelog or issue with the root cause and the verification command.
- Distinctive: line 136
Never paper over a flake with retries.
- Distinctive: line 138
Order dependence: Run the test alone and after the suspect test.
- Distinctive: line 139
Shared state: Look for module-level caches, singletons, database rows, environment variables.
- Distinctive: line 140
Time: Check clocks, time zones, DST, and timeouts.
- Distinctive: line 141
Concurrency: Look for unsynchronized writes, ports, temp files.
- Distinctive: line 144
Resource limits: Check file descriptors, memory, and test timeouts.
- Distinctive: line 151
Delta debugging: Remove inputs and code paths until the failure disappears.
- Distinctive: line 184
Do not edit a test to make it pass unless the test itself is wrong.
- Distinctive: line 185
Do not mix a behavior fix with a refactor.
- Distinctive: line 186
Do not delete or skip a failing test to get a green run.
- Distinctive: line 187
Do not claim a fix without the command and its output.
- Distinctive: line 188
Do not add retries to hide a flake.
- Distinctive: line 189
Do not test private helpers when a public behavior is available.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Test-First Fix
A bug fix is a claim that behavior changed in a specific way. Without a failing test, you cannot tell whether the behavior changed, whether it changed for the stated reason, or whether it will stay changed.
The sequence is fixed: reproduce, isolate, fail, fix, pass, broaden. Skipping a step produces a patch that looks right and fails later.
When to use
Use this skill when:
- A user reports incorrect behavior with a reproducible path.
- A test fails and the cause is not obvious.
- A change caused a regression.
- A test passes locally and fails in CI, or the reverse.
- An agent proposes a fix without showing a failing test.
Do not use this skill for pure refactors with existing coverage. Use it when behavior is in question.
Workflow
1. Capture the report as facts
Write down, before touching code:
- Exact command that triggers the bug.
- Expected output and actual output.
- Runtime, package manager, OS, and commit.
- Input that matters, minimized.
- Whether it fails every time or intermittently.
git rev-parse HEAD
node --version
npm --versionIf the report cannot be reproduced, stop and ask for the missing input. Do not guess at a fix for an unreproduced bug.
2. Shrink the reproduction
Remove everything that is not required. The target is the smallest input and shortest path that still fails. Shrinking usually reveals the cause before you write any code.
For a CLI:
printf '{"amount": 0}' | node cli.mjs --format jsonFor a function test, call the function directly and skip the framework around it.
3. Write a failing test
Add the test at the lowest level that still exercises the bug. Assert on behavior, not on implementation details.
import test from 'node:test';
import assert from 'node:assert/strict';
import { splitAmount } from '../src/split.mjs';
test('splitAmount keeps cents when splitting three ways', () => {
const parts = splitAmount(100, 3);
assert.equal(parts.reduce((sum, part) => sum + part, 0), 100);
assert.deepEqual(parts, [34, 33, 33]);
});Name the test after the broken behavior. Run it alone:
node --test test/split.test.mjs4. Prove the failure is the right failure
Read the assertion output. It must fail because of the bug, not because of a typo, a missing import, or an environment problem.
A test that fails with TypeError: splitAmount is not a function proves nothing about cent allocation. Fix the test setup first.
5. Form one hypothesis
State it as a sentence:
The split rounds each share down independently, so the remainder is dropped instead of being distributed.
Find the exact line. Read the surrounding code and its callers. Check the input types and units. Check assumptions about ordering, time zones, floating point, and empty collections.
If you have more than one hypothesis, rank them and test the cheapest first. Do not change code while testing a hypothesis.
6. Apply the smallest fix
Change one thing. Keep the diff reviewable. Do not refactor adjacent code, rename variables, or reformat the file.
Run the single test:
node --test test/split.test.mjsThen run the module and the full suite:
node --test
npm run lint7. Broaden verification
- Run the tests that cover direct callers.
- Run the full suite once.
- Run the reproduction from step 1, not only the test.
- If the bug involved time, run with a fixed clock or a different time zone.
- If the bug involved concurrency, run the test repeatedly.
- If the bug involved a browser, check the real browser, not only the unit test.
8. Prevent the next one
Add a regression test that is specific enough to fail if the fix is reverted. If the bug came from a missing invariant, add an assertion where the invariant is established.
Update the changelog or issue with the root cause and the verification command.
Flaky tests
Never paper over a flake with retries. First classify it.
- Order dependence. Run the test alone and after the suspect test.
- Shared state. Look for module-level caches, singletons, database rows, environment variables.
- Time. Check clocks, time zones, DST, and timeouts.
- Concurrency. Look for unsynchronized writes, ports, temp files.
- Network. Mock or isolate the endpoint; never depend on the public internet in unit tests.
- Randomness. Seed the generator and record the seed.
- Resource limits. Check file descriptors, memory, and test timeouts.
A flaky test is a bug in the test or the code. Retrying it reduces the signal.
Debugging techniques that pay off
- Bisect history.
git bisect start, mark good and bad commits, run the failing test as the check. - Delta debugging. Remove inputs and code paths until the failure disappears; the last removed piece matters.
- Trace instead of print. A debugger or structured trace shows state without editing the code under test.
- Assert the invariant early. A failing assertion at the source beats a wrong value three layers later.
- Compare working and broken runs. Diff the inputs, versions, environment, and call order.
- Read the error twice. The first line names the failure; the stack names the path; the cause often hides in the middle.
Examples
Bug report: "CSV export sometimes writes 99 cents for a $1.00 order split three ways."
Weak fix:
// Give the remainder to the first element.
parts[0] += total - parts.reduce((sum, part) => sum + part, 0);This hides the rounding rule in one call site and leaves the other callers wrong.
Better fix:
export function splitAmount(totalCents, ways) {
const base = Math.floor(totalCents / ways);
const remainder = totalCents - base * ways;
return Array.from({ length: ways }, (_, index) => base + (index < remainder ? 1 : 0));
}The function now owns the invariant: the parts always sum to the total. The test asserts the invariant and the distribution.
Guardrails
- Do not edit a test to make it pass unless the test itself is wrong. If it is wrong, fix the test in a separate commit with an explanation.
- Do not mix a behavior fix with a refactor.
- Do not delete or skip a failing test to get a green run.
- Do not claim a fix without the command and its output.
- Do not add retries to hide a flake.
- Do not test private helpers when a public behavior is available.
Verification checklist
- Reproduction command recorded before the fix.
- Failing test added and fails for the stated reason.
- Test fails on the original code and passes on the fix.
- Fix is minimal and scoped.
- Full relevant suite passes.
- Original manual reproduction now succeeds.
- Regression test remains in the suite.
- Root cause documented in the issue or changelog.
References
references/debugging-playbook.mdcontains environment, concurrency, and production-debugging checklists.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

