Why feeding AI your whole codebase makes it dumber
Tools11 min read

Why feeding AI your whole codebase makes it dumber

How full-codebase context dumps cause attention dilution and hallucination, and five practical context-isolation engineering principles for real projects.

At 3:15 a.m., a PagerDuty alert shrieked from an on-call engineer’s smartphone. The payment approval success rate of a payment gateway service was plunging to 0% in an instant. The cause was a pull request (PR #1428) that had just been auto-merged into the production branch.

The senior engineer opened a terminal, checked the git diff of the offending commit, and was stunned.

- import { StripeClient } from "@stripe/stripe-node";
+ // AI Agent Refactoring: Optimized for lightning payment flow
+ import { FastStripeStream } from "@stripe/lightning-stream-v3";
+ const client = new FastStripeStream({ ultraFast: true });

The package @stripe/lightning-stream-v3 was a fake module that did not even exist in the official npm registry. A single offhand line of natural language handed to a coding agent tool, “optimize this code to cut payment latency,” had made the language model synthesize a plausible-sounding phantom library out of its latent space, quietly delete the essential payment validation logic around it, and paralyze the entire system.

Theo (t3.gg), a well-known open-source developer and tech influencer, hit on the essence of this disaster in a recent technical critique video. His diagnosis: the critical flaw most developers run into with coding agents is not a lack of intelligence in the AI model, but the fact that the way developers inject context into the model is fundamentally wrong.

The era of “prompt engineering” as a magic incantation is over. What working engineers need now is a rigorous, systems-engineering approach: context engineering. This article digs into the concrete mechanisms behind why a “context dump,” which mindlessly copies and pastes tens of thousands of lines of source code into the prompt window, inevitably collapses the model’s attention, and what kind of deterministic harness you need to build to generate production-grade software safely.


The context dump and the attention dilution mechanism

The most common mistake many developers make when they first pick up an agentic coding tool (Claude Code, Cursor, Windsurf, and the like) is the naive assumption that “the more information I give the model, the smarter its judgment will be.” They pour everything into the context window: the entire repository tree, every TypeScript interface, past commit logs, even a 20,000-line database migration script.

But the self-attention mechanism of the transformer architecture does not guarantee unlimited focus. Once the context length passes 32K, 64K, or 128K, the softmax weights inside the model get spread extremely thin across thousands of tokens. Researchers call this “attention dilution,” or the backfire of the “needle in a haystack” phenomenon.

Spec-driven context splitting and isolated agent execution architecture

As the architecture diagram above makes clear, in a monolithic context dump pipeline, irrelevant utility functions and legacy interfaces compete with the core business logic for the same share of attention. As a result, the model develops the following three serious cognitive distortions.

  1. Recency bias and forgetting the middle (Lost in the Middle)
    Tokens at the very beginning or end of a prompt get relatively high attention, but a key constraint inserted in the middle (for example, “the transaction isolation level must be SERIALIZABLE”) gets ignored entirely.

  2. Phantom dependency synthesis (Phantom Import Hallucination)
    Old library specs and new API specs scattered through a huge source dump get mixed together in the model’s latent space, so it generates code that fluently calls methods of third-party packages that were never even installed in the project.

  3. Arbitrary deletion of existing defensive logic (Destructive Refactoring)
    When the context tokens fill up and the maximum generation budget runs short, the model arbitrarily condenses or deletes the complex exception handlers, mutex locks, and null checks around the code while adding the new feature you asked for.

Instruction-following rate and fake import hallucination rate as context token size grows

Real production refactoring benchmark data shows a clear correlation between context size and generation quality. In an environment where the context is tightly limited to around 8K, the instruction-following rate reaches 98.5% and the fake import rate is only 1.2%.

In a full-codebase dump environment of 128K or more, on the other hand, the fake import rate soars to 41.5% and the instruction-following rate plunges to 48.0%. The more tokens you push in, the model does not get smarter; it gets intellectually paralyzed.


T3 Code’s tool call isolation architecture

To solve this problem, Theo shared the internal design principles of T3 Code, an experimental tool he is building. The key is not to open the entire file system to the agent without limits, but to put the return payload of each tool call on an extreme diet.

Older, simple AI assistants read in every related file in the project whole when a user said “fix the login bug.” Next-generation agent architectures instead adopt the following three-stage context virtualization approach.

Theo's three isolation principles for agent tool calls
  • Precise AST symbol lookup: Instead of reading whole files as text, the agent extracts only specific function signatures and interface type definitions through a language server (LSP) and injects those.
  • Sliding edit window: Only the range within 20 lines before and after the block that needs editing is isolated and given to the model, while the rest of the original file is protected by an in-memory hash.
  • Ephemeral session context: When a subtask (for example, a database migration) is complete, its work log is immediately discarded from the master session, and only the interface of the resulting artifact is returned to the parent agent.

This approach matches exactly how a senior human engineer delegates work to a new hire. A senior engineer does not tell a junior to go read the company’s entire one-million-line codebase. They hand over just two pages: the API input/output spec to implement this sprint and the unit test specification that has to pass. The essence of context engineering is not trusting the model’s vast intelligence, but systematically controlling the model’s cognitive overload.


Five implementation principles of context engineering

Here are five concrete practical principles that engineering organizations must follow to safely land coding agents in their production workflows.

Principle 1. Write an executable spec first, not a natural language command

A vague natural language prompt such as “implement account deletion cleanly” produces missed edge cases and broken data integrity 100% of the time. In practice, before instructing the agent to write code, you must first have it generate a structured, markdown-based spec file.

The spec file should state the endpoint path, required headers, the input JSON schema, the possible HTTP error codes (400, 401, 403, 409, 500), and the database cascade delete policy. This spec file itself becomes the single source of truth and the context anchor for the next-stage agent.

Principle 2. Inject a failing TDD test harness first

Before generating code, write a failing unit test (Red Stage) and mount it in the execution environment. The top-priority context to inject into the agent is not hundreds of lines of business code but the clear error stack trace spat out by the test framework.

The agent does not write code from abstract imagination; it computes only the minimal diff needed to turn a failed assertion into a success (Green Stage). This blocks unnecessary code over-engineering at the source.

Principle 3. Surgically minimize the context window scope

Do not hand more than 10 file paths to a single agent session. Ban directory-level wildcard lookups (src/**/*.ts), and supply only the file to be modified and the declaration-level type definition files (.d.ts) it directly depends on, specified as a whitelist.

Principle 4. Combine a deterministic static analyzer and a lint feedback loop

A patch generated by the model must pass a mechanical static analysis gate before a human looks at it. Feed the results of the TypeScript compiler (tsc --noEmit), the linter (eslint), and the security scanner (semgrep) straight back to the agent as feedback, forcing the model to make its own first-pass fixes for syntax errors and type mismatches.

Principle 5. Commit incrementally and reset the session to prevent long-term memory pollution

Do not try to finish everything in one prompt session, from feature planning through database design, API development, and frontend UI binding. Every time a logical unit is complete and passes its unit tests, run git commit immediately and fully reset the conversation session. Accumulated conversation history is the most dangerous poison that drags a model into a swamp of hallucination.


An isolated verification harness implementation example

The code below is a TypeScript-based mini context harness. It does not expose the entire file system to the agent; it supplies only the type definitions and unit tests in isolation, then converges on a safe patch through compiler feedback.

// context-harness.ts: harness module that verifies agent code generation in a deterministic, isolated environment
import { execSync } from "node:child_process";
import { readFileSync, writeFileSync } from "node:fs";

export interface SpecContract {
  featureName: string;
  targetFile: string;
  typeDefinitionFile: string;
  unitTestFile: string;
  maxTokenBudget: number;
}

export class ContextEngineeringHarness {
  private spec: SpecContract;

  constructor(spec: SpecContract) {
    this.spec = spec;
  }

  // Extract only the minimal interface context needed for compiler verification, instead of the full code
  public buildMinimalContext(): string {
    const typeDef = readFileSync(this.spec.typeDefinitionFile, "utf-8");
    const testCases = readFileSync(this.spec.unitTestFile, "utf-8");

    return [
      `### FEATURE SPEC: ${this.spec.featureName}`,
      "Strict Rule: Do NOT import any external module not present in the type contract.",
      "Strict Rule: Your output MUST satisfy 100% of the assertions in the test suite.",
      "",
      "--- [ALLOWED TYPE CONTRACT] ---",
      typeDef,
      "",
      "--- [TARGET TEST SUITE (RED)] ---",
      testCases,
    ].join("\n");
  }

  // Write the agent's proposed patch to the isolated sandbox file and decide whether it passes the deterministic verification gates
  public verifyPatch(candidateCode: string): { success: boolean; errorLog?: string } {
    try {
      // Step 1: write the minimal change only to the isolated target file
      writeFileSync(this.spec.targetFile, candidateCode, "utf-8");

      // Step 2: static verification with the TypeScript compiler in strict mode
      execSync("npx tsc --noEmit --strict", { stdio: "pipe" });

      // Step 3: run the isolated unit tests
      execSync(`npx vitest run ${this.spec.unitTestFile}`, { stdio: "pipe" });

      return { success: true };
    } catch (error: any) {
      // On failure, slice out only the key error message from the system log and return it as the agent's fix context
      const stderr = error.stderr ? error.stderr.toString("utf-8") : error.message;
      return {
        success: false,
        errorLog: stderr.slice(0, 1500), // cap the error log at 1,500 characters to prevent attention dilution
      };
    }
  }
}

With this harness, the context handed to the agent shrinks by more than 95% compared with a full codebase dump (hundreds of thousands of characters), down to around 5,000 characters. And when a test fails, instead of spewing the entire stack trace, it cuts only the specific type mismatch lines flagged by the compiler to within 1,500 characters and feeds them back to the agent, completing an accurate first-pass fix loop.

Practical defect rate comparison between plain vibe prompting and context engineering

As these measured figures show, with plain vibe prompting the share of broken unit tests reaches 62.1% and the type-check error rate 58.4%. Work that passed through a precise context engineering harness drops sharply to 4.0% broken tests and 3.2% type errors, and the rate of hallucinated package imports converges to practically zero.


A three-layer strategy for agent rule files

One of the keys to context engineering is keeping the meta configuration file that the agent reads on entering a project extremely slim and clear. Many developers mistakenly fill this file with hundreds of lines of internal coding conventions or long-winded business philosophy, but that is the main culprit that pointlessly eats up the agent’s first context slot.

The best agent rule file, proven in practice, should be split into the following three layers.

# [Workspace Agent Core Contract]
# 1. Scope Boundary
- Never scan or index files outside of the explicitly requested directory.
- For all refactoring tasks, you must preserve existing public API signatures exactly.

# 2. Strict Compiler Verification
- After modifying any TypeScript file, run: `npx tsc --noEmit`
- After updating API routes, run: `npm run test:contracts`
- If any check fails, do NOT proceed. Immediately fix the offending lines.

# 3. Code Generation Restraints
- Never generate mock or placeholder implementations (e.g., "// TODO: implement later").
- Never introduce new third-party npm dependencies without explicit user confirmation.
- Output concise git-friendly diffs instead of re-printing entire files.

When you leave only clear, measurable constraints in the rule file like this, the model does not wander off mid-task and operates within a strict track.

The longer the rules get, the less the model follows them. The shorter the rules and the more directly they tie to compiler commands, the more the model produces flawless code, indistinguishable from what a senior human developer would write.


A four-point checklist for context engineering

Tech leads and architects who want to bring coding agents into a production pipeline should establish the following four questions as an engineering standard.

Check area Key verification item Defect type if unmet Recommended production fix
Context size Is a single prompt payload 10KB (about 3,000 tokens) or less? Arbitrary omission of existing defensive logic caused by attention dilution Extract and supply only AST-based type interfaces
Spec first Is a markdown spec defined before the natural language request? API I/O mismatches and unhandled edge cases Write the spec first, including I/O schemas and HTTP status codes
Test harness Does a failing unit test exist before code is generated? Fake code that looks like it works but actually fails Inject a Vitest / Jest failing fixture at the very top of the context
Session invariance Is the conversation history reset after each unit of work? Stale assumptions from earlier conversation pile up and interfere with new work Force-spawn a fresh agent session as soon as each unit commit is done

We also recommend running a “context linter” in the CI/CD pipeline to raise the reliability of agent output. It is a mechanism that automatically raises a compiler error and halts the send when the token size of the prompt going to the agent exceeds a threshold (for example, 8,000 tokens), or when the payload includes a list of unused files that are never referenced. With this kind of pre-filtering layer in place, the agent only ever learns from the cleanest, most orderly interfaces, free of hallucination or derailment.

Paradoxically, as AI coding tools advance, the most important skill for developers is not flashy natural language prompt-writing tricks. It is the modularization skill to draw the boundaries of software, the strict interface design ability to lower external coupling, and the deterministic engineering fundamentals that firmly confine the probabilistic output of AI. Clearing away unnecessary noise and building cold safety devices such as the compiler and the test harness: that is the essence of context engineering that a senior software engineer needs in 2026.

#context engineering#prompts#coding agents#Claude Code#software architecture