The Drift Log · Governing agents that write code
Verifying AST Invariants Before Agent PRs Enter Review
25 October 2026 · 4 min read · 832 words · established

Block architectural violations from AI coding agents by enforcing AST-based module boundaries and sink constraints before PR creation.
A pull request lands with four hundred lines of clean TypeScript. The types compile without warnings. The unit tests pass—largely because the agent wrote the tests to assert its own assumptions. A senior engineer scans the diff, approves it, and merges.
Two weeks later, an incident reveals that the agent solved a data-fetching bottleneck by importing an internal database connection pool directly into a UI presenter, bypassing the service layer, caching, and tenancy checks.
The code looked reasonable in a standard diff. The logic worked in isolation. But the structural architecture of the repository was quietly breached.
When humans write software, architectural violations are usually lazy shortcuts. When AI coding agents write software, architectural violations are mathematical path-of-least-resistance solutions. The model’s objective is to satisfy the prompt and pass the immediate test suite, not to preserve your architectural boundaries.
Human reviewers cannot safely parse hundred-line agent diffs for structural integrity without mechanical help. The defense is an automated invariant check run against the Abstract Syntax Tree (AST) before the write ever becomes a pull request.
Line Diffs Obscure Structural Drift
Traditional code review automation relies on linters and text-based diffs. Linters check local syntax, formatting, and trivial smells within a single file. Text diffs show what changed line by line.
Neither tool understands architectural intent. A diff cannot tell you that a newly added function call crosses a domain boundary that has been off-limits for four years. It cannot tell you that an agent synthesized an ad-hoc JSON parser instead of using the canonical data transformation utility already present in the codebase.
When evaluating agent governance, the fundamental control point is not the prompt or the model's system message. Prompt instructions like "do not bypass the repository layer" degrade over long contexts. The only durable enforcement point is the gate between agent decision and commit.
Before an agent’s proposed write is turned into a branch or submitted for review, the engine must parse the modified codebase into an AST and test it against explicit invariants.
Agent Proposed Patch
│
▼
┌───────────────────────────────┐
│ AST Extraction & Graph Build │
└───────┬───────────────────────┘
│
▼
┌───────────────────────────────┐
│ Invariant Verification Engine │
│ ── Domain boundaries │
│ ── Call-graph whitelist │
│ ── Primitive canonicalization │
└───────┬───────────────────────┘
│
Pass │ Fail ──► Reject Write Intent
▼
Pull Request Created
Three Invariants to Enforce on the Tree
An AST exposes the syntactic structure of source code as a traversable node graph. By walking this graph, a build gate can enforce structural rules that standard linters miss.
1. Import and Dependency Directionality
The simplest AST check inspects ImportDeclaration nodes. You define a directed acyclic graph (DAG) of your modules. If an agent proposes a patch in src/interfaces/http that imports from src/infrastructure/db, the gate rejects the write intent immediately. The agent never gets to submit the PR.
2. Call-Graph and Sink Containment
Agents frequently hallucinate or reach for low-level system APIs when higher-level domain abstractions feel too constrained. An AST visitor can walk CallExpression nodes to ensure sensitive operations—raw SQL execution, filesystem writes, network fetches—occur strictly within designated module boundaries.
If an agent attempts to instantiate a raw network socket inside a domain entity, the invariant engine catches the unapproved call site.
3. Canonical Primitive Enforcement
When an agent needs to transform a data structure, it will often generate forty lines of bespoke traversal logic. This bloats the codebase and introduces untested edge cases.
An invariant check can enforce that specific operations (such as UUID generation, date parsing, or currency formatting) use approved workspace primitives. By scanning AST identifier nodes, the gate can mandate that utility functions match a known catalog of components rather than ad-hoc inline routines.
What Structural Invariants Cannot Do
AST invariant verification is structural, not semantic. It proves where data can flow, which functions may be invoked, and what boundaries remain intact.
It does not prove that the algorithmic logic inside a permitted function is correct. It will not catch a subtle off-by-one error in a calculation or an inverted boolean in business logic that satisfies the type checker.
Treating AST analysis as an absolute guarantee of correctness is a mistake. Its purpose is narrower and more practical: it strips away structural drift and boundary violations before a human ever looks at the code. It ensures that when a reviewer opens a pull request, they are evaluating business logic, not hunting for architectural sabotage.
This structural clearance is a core requirement of governing code agents at the build intent gate.
What to Do on Monday
Do not attempt to write a full architectural rulebook on day one. Start with one structural blind spot:
- Identify your most critical architectural boundary (for example: "Domain models must not import persistence adapters").
- Write a minimal script using an AST tool (such as
ts-morphfor TypeScript,ast-grep, orsemgrep) that walks import nodes and asserts this single rule. - Wire this check into your CI pipeline as a mandatory status check, or run it directly against your agent execution harness.
- Set the policy to reject the run automatically if the rule fails.
Once your build gate rejects boundary violations deterministically, human reviewers can stop acting as human compilers and focus on whether the software actually does what the business requires.
Keep reading
Next in the log
- Policy-Driven Quotas for Agent-Generated Write Intent
Token metering tracks text volume rather than architectural impact. Gating registered write intents protects finite engineering review capacity.
- Build‑Intent Review Bot for Agent‑Generated Pull Requests
A lightweight GitHub Action can enforce the Build‑Intent gate on agent‑generated pull requests, ensuring licence and invariant checks before any merge.
- Immutable Log of Build‑Intent Write Proposals for Auditable Post‑Mortem Review
An immutable, hash‑chained log of Build‑Intent proposals gives a verifiable audit trail for post‑mortem review.
The Strategic Master Library · written and reviewed under the house's own epistemic rules: nothing claimed that we cannot show.