TL;DR

  • AI-generated code drifts faster than humans can review it. Probabilistic checks fail to catch semantic violations.
  • Free-text instruction files (CLAUDE.md, etc.) are configuration in the wrong shape; they lack precedence and lifecycle.
  • The solution is ‘Engineering Governance’: a layer that translates architectural decisions into deterministic, executable fitness functions.
  • Enforcement must happen in CI via tools like ArchUnit or dependency-cruiser, not via a second LLM review.

The Drift Velocity Problem

Priya’s pull request compiled. It passed every unit test. It also silently bypassed the audit logging system the team banned two years ago. The AI agent that wrote it followed idiomatic patterns for direct database writes because the architectural decision record (ADR) that forbade them sat in a directory the agent never saw.

This is a memory problem. The gap between generated code and surviving code is widening because AI agents operate at a velocity that outpaces human recall. Faros AI published a report in 2026 based on telemetry from more than 22,000 developers. It noted that as AI-code acceptance rates rose from 20% to 60%, code churn increased 861% over the same interval. Faros noted this number may include productive refactoring. The data exposes a gap between code entering the repository and code that survives there. Architectural drift—code that individually looks fine but collectively pulls the codebase away from where the team agreed it should go—is one plausible contributor.

Agents write code that respects syntax but ignores history. They do not read versioned markdown files unless explicitly injected. They do not understand the “why” behind a routing choice. When an agent produces 340 lines of clean, functional code that violates a buried team standard, the reviewer sees a passing build, not a structural violation. The drift happens in the invisible gap between what the code is and what the team agreed it should be.

Traditional guardrails fail here. Linters check for return types, not semantic boundaries. SCA tools flag vulnerable libraries, not internal routing errors. Human reviewers cannot scale to catch drift in high-velocity agent output. The context required to validate the code is missing. We are trying to enforce deterministic architectural decisions with probabilistic context injection. That approach does not hold.

Why Prompts Are Not Guardrails

Free-text markdown files like CLAUDE.md or .github/copilot-instructions.md fail as guardrails because they lack precedence rules and lifecycle management. When two rules contradict each other, nothing arbitrates. When a rule is violated, nothing catches it. These documents sit in the shape of configuration but function as suggestions. The AI reads them, but the team cannot verify compliance against them.

Standards must be infrastructure, not documentation. We need to shift from vague context injection to executable architectural fitness functions. We need tools that enforce boundary integrity deterministically. They do not guess intent. They check structure. If the code violates the rule, the build fails. No debate. No memory lapse.

This layer connects recorded engineering decisions to the tools that generate code. It holds decisions in a structured corpus with metadata. It retrieves relevant rules reliably. It injects them into the AI’s context before generation. Most importantly, it enforces them in continuous integration. The verdict is traceable to a specific ADR and a specific line of code.

Probabilistic systems may retrieve or recommend. They should not determine enforcement. Every block must reconstruct from artifacts on disk: the code, the ADR, and the rule text. This discipline closes the gap between what the team decided and what the AI writes. It stops drift before it compounds.

The Enforcement Layer: Determinism Over Probability

Deterministic tools turn architectural intent into executable truth. They replace the probabilistic guesswork of AI generation with binary enforcement. The AI might write code that compiles, but it cannot violate a rule it can’t see. These tools bridge the gap between static documents and dynamic code. They enforce the Standards as Infrastructure model by validating structure at compile time or CI, not after the fact.

ArchUnit handles Java and Kotlin. It uses JUnit 5 to define rules like noClasses().that().resideInAPackage("..domain.model").should().dependOnClassesThat().resideInAPackage("..ui"). If the AI generates a direct database write bypassing the service layer, ArchUnit fails the build. The error is deterministic. It cites the specific rule and the violating class. No ambiguity.

Operationalizing the Guardrails

First, standardize AI context injection via explicit file conventions. Treat AI interaction instructions as versioned, reviewed artifacts. This shifts the burden from human memory under time pressure to consistent, executable prompts, addressing the ‘prompting inconsistency’ gap where junior engineers lack the instincts to specify critical constraints. Without this, agents explore infinite loops, burning tokens and time.

Second, enforce architectural rules in CI. These tools act as circuit breakers for architectural drift. When Priya’s PR bypasses the customer service API, the build fails. It does not ask. It cites the specific rule and the violating class. This deterministic check prevents semantic violations from reaching production. You cannot lint your way out of a bad design, but you can block it at merge.

Third, demand traceable verdicts. Every block must link to the specific ADR and the rule that failed. Ambiguity is the enemy of enforcement. If the agent cannot see the decision, the reviewer must. But relying on human memory is a leaky abstraction. Version the decisions. Inject them into the context. Catch the violation before it ships. This creates a feedback loop where the codebase enforces the history. The system remembers what the team forgot. That is the only way to keep velocity without sacrificing integrity.

References