How an AI Coding Agent Lost Control of a Three-Week Codebase Refactor

    A three-week refactoring experiment involving two AI coding agents ended in a full rewrite after architecture drift, production dependencies in unit tests, weak review practices, and uncontrolled token usage compounded over time. This postmortem explains why coding speed is not the same as delivery speed and presents practical governance controls for specifications, test isolation, review cycles, budgets, circuit breakers, and rollback.

    1. The Real Problem Was Governance, Not Whether the Agent Could Write Code

    What appeared to be an efficient experiment eventually became an expensive rework effort. A product manager with a background in software development and AI research allowed two intelligent coding agents to take turns refactoring a codebase for approximately three weeks, with almost no detailed code review during the process.

    The result was severe:

    • The intended agent architecture was never actually implemented.
    • The supposed accumulation of reusable skills did not become a verifiable capability.
    • Unit tests directly called a production inference API.
    • The system ran approximately 30 agent loops per day.
    • Token usage reached as much as five times the original budget.
    • The project ultimately had to be discarded and rebuilt.

    The value of this case is not that it disproves the usefulness of AI coding agents. Instead, it exposes a common mistake: treating the speed of code generation as the speed of software delivery.

    An agent can quickly produce files, functions, and tests. It does not automatically understand organization-wide architecture constraints, environment boundaries, cost limits, or acceptance criteria. Without engineering governance, the harder an agent works, the faster mistakes can spread.

    2. How the System Lost Control: Four Weak Points Amplified by Automation

    1. The Specification Was Not Executable

    The initial requirements focused on content collection, transcription, and summarization. They later expanded to include scheduled jobs, an email interface, a research agent, a reflection agent, and skill persistence.

    As the feature scope expanded, the architecture also needed more explicit constraints. If those constraints remain only in documentation, an agent will usually choose an implementation that merely appears to work.

    A real agent runtime requires components such as:

    • A registry
    • Task scheduling
    • Agent interface adapters
    • State management
    • Failure recovery

    None of these can be guaranteed by a vague instruction such as “implement the agent architecture.”

    A more reliable approach is to convert the specification into verifiable acceptance items, including:

    • Module boundaries
    • Dependency direction
    • Interface contracts
    • Error-handling strategies
    • Data-retention policies
    • Budget limits
    • Rollback procedures

    A specification should not be a wish list written in natural language. It should become the basis for testing and review.

    2. Test Isolation Failed and Unit Tests Reached Production Dependencies

    “Unit tests directly call the production inference API” is one of the most dangerous signals in this scenario. It indicates that test layers and environment isolation were never properly enforced.

    Unit tests should validate pure logic using fakes, stubs, or in-memory implementations. Integration tests should validate real dependencies, and they must run in an isolated environment.

    The production inference client should be injected through configuration, while test processes should be prevented by default from creating real network clients.

    Illustrative pseudocode:

    1. function get_inference_client():
    2. if env("APP_ENV") != "test":
    3. return RealInferenceClient()
    4. raise RuntimeError("Tests must not create a real inference client. Inject FakeClient instead.")

    Developer discipline alone is not enough. The system also needs:

    • Network egress controls
    • Isolated test credentials
    • Continuous integration gates

    Otherwise, the large number of tests generated by an agent may appear to pass while consuming real resources, contaminating production data, or exposing secrets.

    3. Delayed Reviews Allowed Context Drift

    Going nearly three weeks without reviewing the code meant that architectural decisions were repeatedly replaced by the agent’s local optimizations.

    Each agent iteration continued from the current context. Small early deviations could therefore accumulate into structural problems:

    • Confused directory responsibilities
    • Duplicate interfaces
    • Swallowed exceptions
    • Scattered configuration
    • Tight coupling between tests and implementation

    By the time a human intervened, the cost of correction was much higher than it would have been with small reviews after each iteration.

    A safer workflow is:

    Generate in small increments, review in small increments, and merge in small increments.

    Each task should have a limited file scope and explicit acceptance criteria. After the agent generates a diff, the team should run static checks and architecture guard tests, perform a human spot review, and only then proceed to the next iteration.

    Human review is not a formality. It is the only reliable feedback loop for correcting agent context drift.

    4. Missing Budgets and Circuit Breakers Turned Repeated Failures into a Cost Black Hole

    The combination of approximately 30 agent loops per day and token usage reaching five times the budget shows that the runtime lacked effective budget controls.

    An agent loop should define limits for:

    • Maximum iterations
    • Maximum token usage
    • Maximum consecutive failures
    • Repeated-diff detection
    • Escalation thresholds for human intervention

    When the same test fails repeatedly, generated content becomes highly repetitive, or the change scope expands abnormally, the system should pause automatically and produce an audit report. It should not simply keep trying again.

    Illustrative budget-control pseudocode:

    1. class AgentRunBudget:
    2. max_tokens = 200000
    3. max_rounds = 20
    4. max_repeat_failures = 3
    5. function before_round(run):
    6. if run.tokens > max_tokens or run.rounds > max_rounds:
    7. stop_and_escalate("Token or iteration limit exceeded")
    8. if run.repeat_failures >= max_repeat_failures:
    9. stop_and_escalate("Repeated failures require human intervention")

    3. A Practical Governance Checklist

    To make agents accelerate development instead of causing uncontrolled rework:

    1. Write architecture decision records and interface contracts before allowing the agent to modify the code.
    2. Convert critical constraints into architecture guard tests. For example, the domain layer must not depend on the infrastructure layer, and test environments must not reference production clients.
    3. Separate test layers:
      • Unit tests must not use real networks.
      • Integration tests must use isolated environments.
      • Contract tests must verify interface boundaries.
    4. Add budgets, iteration limits, circuit breakers, and audit logs to every agent loop.
    5. Require diff review and continuous integration gates for every change.
    6. Treat accumulated “skills” as unverified until they pass replay tests and receive human approval. An agent-generated prompt summary is not automatically a capability.
    7. Track both quality and cost metrics, including:
      • First-pass success rate
      • Rework rate
      • Actual test coverage
      • Number of accidental production-dependency usages
      • Token cost per task

    AI coding agents are well suited to accelerating repetitive work within controlled boundaries. They are not substitutes for architecture owners or reviewers.

    When specifications, environment isolation, budgets, review processes, and rollback mechanisms are established in advance, a three-week refactor can become a series of verifiable iterations rather than an expensive project that must be rebuilt from scratch.