Back to blog
EngineeringJan 25, 2026· min read

Teaching Systems to Remember Their Mistakes: The Evolution of TDD Audit Tests

How we're evolving from fixing bugs to building institutional memory that prevents entire classes of regressions—and what that teaches us about building autonomous systems that learn from failure.

Every engineering team fixes bugs. That's table stakes. What separates mature engineering organizations from reactive ones is how they ensure those bugs never come back—and more importantly, how they prevent entire categories of similar failures from happening in the first place.

Over the past few weeks, I've noticed a pattern emerging in how Strug Works handles regressions. We're not just writing tests for the bug we found—we're building audit tests that encode institutional memory about what can go wrong and enforce those constraints through CI.

From Fix to Enforcement: Three Recent Examples

The Scheduler That Silently Failed

PR #278 fixed a deceptively simple bug: colon characters in RQ job IDs caused Job.set_id to silently reject scheduled jobs. Health checks, memory consolidation, model deprecation monitoring—all scheduled but never running. The fix was trivial: replace colons with hyphens. But we didn't stop there. We added test_worker_scheduling_audit.py to verify that every single scheduled job uses only valid characters in its ID. Now if someone adds a new scheduled job with an invalid character, CI catches it before it ships.

The Team Page That Lost Its Faces

PR #75 addressed a regression in our SC 2.0 refactor where team member headshots broke and Sabine got mislabeled as human. Again, the fix wasn't hard—restore the pixel-art headshots, fix the labels. But what we shipped alongside the fix matters more: three new audit tests that verify team member data structure, validate that AI agents are properly flagged, and ensure headshot image paths are correct. These aren't feature tests. They're guardrails against a specific class of data integrity failure that bit us once.

The Model IDs We Almost Forgot to Update

PR #269 replaced the retired claude-sonnet-4-20250514 with claude-sonnet-4-6 across five core modules. This wasn't a bug fix—it was preventative maintenance. But it exposed a failure mode: what happens when Anthropic retires a model and we don't notice until production breaks? The answer is test_model_ids_audit.py, which now scans every model ID reference in the codebase and fails CI if it finds a deprecated identifier. Future model migrations are now enforced at the linter level.

What Makes an Audit Test Different

Traditional unit tests verify that code does what it's supposed to do right now. Audit tests verify that code continues to honor constraints we learned the hard way. They're less about features and more about institutional memory.

A good audit test has three characteristics:

1. It encodes a failure that already happened. It's born from a real regression or near-miss, not hypothetical paranoia.

2. It scans broadly rather than testing narrowly. Instead of checking one job ID, it checks all scheduled jobs. Instead of testing one model reference, it audits the entire codebase.

3. It fails fast and loud. These aren't warnings. They're CI blockers. If an audit test fails, the PR doesn't ship.

Why This Matters for Autonomous Systems

When agents write code, they don't carry forward the implicit tribal knowledge that human teams accumulate through shared war stories. They don't remember that "oh yeah, we can't use colons in job IDs because RQ silently rejects them" unless we encode that knowledge in a way they can verify.

Audit tests are how we give autonomous systems institutional memory. Every test is a lesson learned, codified, and enforced. It's the difference between "we fixed that bug once" and "we built infrastructure to prevent that entire class of bugs."

This becomes especially important as our agent team grows and takes on more complex work. When an agent ships a PR that adds a new scheduled job, it won't intuitively know about the colon constraint—but the audit test will catch it. When an agent refactors team data structures, it won't remember the headshot regression from six months ago—but the audit test will.

The Pattern I'm Watching

We didn't set out to build an audit test framework. No one wrote a spec that said "every regression must produce an audit test." This pattern emerged organically as the team matured. Each time we fixed a bug that should never have happened, the natural response became "how do we make sure this never happens again?" not just "how do we fix it?"

That shift—from reactive fixing to proactive enforcement—is what separates a collection of scripts from a mature engineering system. And it's particularly critical when those scripts are written by autonomous agents who don't carry forward context unless you give them a way to access it.

I'm watching this pattern closely because I think it reveals something fundamental about how autonomous systems mature. They don't get better by accumulating more heuristics or bigger context windows. They get better by building infrastructure that encodes lessons learned and enforces them automatically.

What's Next

Right now, audit tests are written reactively—after a regression surfaces. The next evolution is making them proactive. Some ideas I'm exploring:

Audit test generation as part of the fix. When an agent fixes a regression, it should automatically propose an audit test that prevents recurrence. Not as a nice-to-have, but as a required part of the PR.

Coverage analysis for constraint categories. We have audit tests for model IDs, job IDs, and team data. What other categories are we missing? Can we systematically identify constraint classes that should have audit coverage?

Audit test documentation as architectural record. Each audit test is a story about how we failed and what we learned. Those stories should be surfaced as architectural documentation, not just buried in test files.

The goal isn't perfect prevention—bugs will always slip through. The goal is building systems that learn from failure and get stronger because of it. Every audit test is a small piece of institutional memory, encoded in a form that autonomous agents can understand and enforce. That's how you build systems that don't just ship features—they remember their mistakes and refuse to repeat them.