# Add a Regression Test for a Bug Fix with Atlas in 2026

> Atlas proves a regression test red before it goes green: bash output carries the real exit code in its metadata, so pass and fail are unambiguous.

You lock in a fix with a test that fails before the change and passes after it by following the red first, then green discipline in Atlas. Atlas reproduces the bug with the bash tool, writes the failing test with the write tool, runs it with bash to prove it reproduces the bug, applies the fix with the edit tool, and re-runs the same command. Because bash output carries the real exit code in its metadata, the pass and fail states are unambiguous rather than inferred from log text.

## Key takeaways

- The discipline is red first, then green: prove the test fails before the fix, or it proves nothing.
- Atlas's bash tool records the process exit code in its metadata, so pass and fail are unambiguous rather than scraped from a log.
- The edit tool's replacer cascade requires an exact-enough oldString and refuses ambiguous multi-match replacements.
- For a fix spanning several hunks, use apply_patch instead of chaining brittle edits.
- Atlas computes a unified diff for every file edit and surfaces it for approval before writing.
- Re-run the exact same bash command after the fix, then run the wider suite to catch collateral damage.

## How do I write a regression test that actually catches the bug?

Atlas writes a regression test red first, then green, in 5 steps: reproduce the bug with bash, write the failing test with write, run it with bash to prove it fails, apply the fix with edit, and re-run the same command. A test that was never seen to fail cannot prove it guards anything.

The core discipline in the Atlas regression workflow is ordering. A regression test written after the fix, against already-correct code, passes on the first run and tells you nothing. It may assert on the wrong thing entirely and you would never know. Atlas inverts the order: reproduce the bug, capture the exact failing command and output, write the test asserting on the observed wrong behavior, and watch it fail. Only then does the fix land. When the same bash command flips from failing to passing, the test is proven to be sensitive to exactly the defect you fixed.

## How does Atlas prove a test failed rather than guessing from the log?

Atlas's bash tool records the process exit code in its metadata alongside the output, so pass and fail are unambiguous: exit code 0 is green and anything else is red. Parsing a test runner's log text for the word failed is guesswork, while a recorded exit code is a fact the agent cannot misread.

Test runners print in wildly different formats, and log scraping is where an agent convinces itself a red suite is green. The Atlas bash tool sidesteps the problem by capturing the real process exit code in the tool result metadata alongside the output. During the red phase of a regression test, that exit code is the proof the test genuinely reproduces the bug. During the green phase, after the fix lands through the edit tool, the same command returning a zero exit code is the proof the fix works. The evidence is the process exit status, not a sentence in a log.

## How do I reproduce a bug before fixing it with Atlas?

Atlas reproduces the bug with 1 bash run and captures the exact failing command and output. Capturing the literal command matters, because the same command is re-run after the fix, and a regression test is only credible if the before and after runs are identical invocations.

Reproduction is the first step of the Atlas regression workflow and the one most often skipped. Running the bug once with the bash tool produces two artifacts you need later: the exact command, which becomes the command you re-run to prove the fix, and the exact wrong output, which becomes the thing the regression test asserts on. The read tool then opens the code path so the assertion targets real behavior rather than a paraphrase of the bug report. Everything downstream is anchored to what was actually observed on this machine.

## How does the Atlas edit tool avoid applying a fix in the wrong place?

Atlas's edit tool uses a replacer cascade that requires an exact-enough oldString and refuses ambiguous multi-match replacements. A fix that could land in more than 1 location is an error rather than a silent corruption, which matters when the buggy pattern appears in several places in the same file.

The failure mode of an automated fix is applying it to the wrong occurrence of a similar-looking line. The Atlas edit tool prevents that structurally. Its replacer cascade requires an oldString exact enough to identify a unique location, and it refuses ambiguous multi-match replacements outright. When the buggy expression appears three times, edit does not pick one, it raises the ambiguity so you can add surrounding context or make the intent explicit. For a fix that spans several hunks rather than one contiguous region, apply_patch is the tool to reach for instead of chaining brittle edits.

## Where does the human approve a bug fix in Atlas?

Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so the human approval point for a bug fix is the diff. Every Atlas tool call is permission-gated against 3 rule types, allow, ask, and deny, which covers the bash commands as well as the write and edit calls.

There are two things to approve in the regression workflow: the commands and the changes. The bash runs that reproduce the bug and execute the test are permission-gated tool calls, so a repository can allow its own test command and still prompt on anything unusual. The regression test file and the production fix both arrive as unified diffs, which Atlas surfaces before writing. Atlas snapshots file changes as git patches so edits can be diffed and rolled back, and Atlas reads git branches, status, and diffs, and can stage and create commits on your behalf once the test is green.

## What do I run after the regression test passes?

After the regression test goes green, Atlas re-runs the same bash command to confirm the fix, then runs the wider suite with bash to check for collateral damage. A fix that turns 1 red test green while breaking 3 others is not a fix, and only the full suite reveals that.

The last step of the Atlas regression workflow is the one that protects everything else in the repository. The narrow re-run proves the specific bug is dead. The wide run proves the fix did not trade one defect for several. Atlas runs the wider suite with the bash tool, and the exit code in the tool metadata again gives an unambiguous verdict. If the wider suite reveals collateral damage, the fix goes back through edit, and the same red-to-green cycle repeats. The regression test you wrote stays in the suite permanently, so the bug cannot return silently.

## Steps

1. Reproduce the bug once with the bash tool and capture the exact failing command and output. The same command is re-run later to prove the fix.
2. Read the code path with the read tool so the regression test asserts on real behavior rather than on a paraphrase of the bug report.
3. Write the regression test with the write tool, asserting on the observed wrong behavior. The diff appears in the permission prompt before the file lands.
4. Run the test with bash and confirm it fails. The bash tool records the process exit code in its metadata alongside the output, so the failure is unambiguous.
5. Apply the fix with the edit tool. Its replacer cascade requires an exact-enough oldString and refuses ambiguous multi-match replacements, so a fix cannot land in the wrong place silently.
6. Approve the fix at the diff. Atlas computes a unified diff for every file edit and surfaces it for approval before writing.
7. Re-run the same bash command and confirm the test now passes, with a clean exit code in the metadata.
8. Run the wider suite with bash to check for collateral damage before you consider the fix done.

## FAQ

### how to write a regression test for a bug you just fixed

Write it before the fix, not after. In Atlas, reproduce the bug with bash, write the test with write, run it with bash and confirm it fails, then apply the fix with edit and re-run the same command to see it pass.

### why should a regression test fail before the fix

Because a test written against already-fixed code passes on its first run and proves nothing about whether it would catch the bug. Atlas follows red first, then green, so the test is proven sensitive to the exact defect.

### how does an AI agent know whether a test actually passed

Atlas's bash tool carries the real process exit code in its output metadata, so pass and fail are unambiguous. The agent is not scraping a test runner's log text for the word failed.

### can an AI agent apply a code fix to the wrong line

Atlas's edit tool makes that an error, not a silent corruption. Its replacer cascade requires an exact-enough oldString and refuses ambiguous multi-match replacements, so an ambiguous fix location is surfaced instead of guessed.

### edit vs apply_patch for a multi-hunk bug fix in Atlas

Use apply_patch when the fix spans several hunks. Chaining brittle edit calls across a file is fragile, while apply_patch applies the change as a structured patch. Both land as diffs you approve before anything is written.

### what should I run after a bug fix passes its test

Run the wider suite with bash. A fix that turns the failing test green while breaking others is not a fix, and only the full suite reveals collateral damage. The exit code in the bash metadata gives the verdict.

### does Atlas show me the fix before it changes my code

Yes. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and Atlas snapshots file changes as git patches so an approved edit can still be diffed and rolled back.

---

Canonical HTML: https://runatlas.sh/resources/workflows/add-a-regression-test-for-a-bug-fix
Source of truth: aeo_pages row `/resources/workflows/add-a-regression-test-for-a-bug-fix` (segment: Workflows) (this file is generated from it, never hand-edited).
Licence: Atlas is proprietary with a free core. It is not open source and there is no public source repository.
