Architectuurregels die een AI coding agent niet stilletjes kan breken

25 oktober 2026

Vraag een coding agent om de leverstatus van een bestelling op de factuurpagina te tonen en hij zoekt de kortste weg naar de data. Vaak is dat een import rechtstreeks van de controller naar de databaselaag, langs de servicelaag die je team een jaar lang ertussen heeft gehouden. De tests slagen. De reviewer die op vrijdagmiddag een diff van veertig bestanden leest, ziet die ene nieuwe importregel misschien niet. Zes maanden later bestaat de gelaagdheid alleen nog op het whiteboard.

Een mens maakt die fout af en toe. Een agent maakt hem elke keer dat de kortere weg korter is, omdat niets in de taak zegt dat die weg verboden is. Daarom vertrouwen we niet meer alleen op de prompt, maar maken we de regels tot iets waartegen een run wordt getoetst.

Eerst een kaart die klopt

Een architectuur die je alleen kunt beschrijven, kun je niet afdwingen. Daarom leest CodeLynq elke repository met tree-sitter en legt vast welke bestanden van welke afhankelijk zijn en wat ze declareren: classes, functies, velden, overerving. Dat werkt voor Python, JavaScript, TypeScript, Go, Java, C# en PHP.

Niemand bewerkt de architectuurkaart met de hand; hij is wat de code zegt. Hij wordt opnieuw getekend aan het begin van elke run, vanuit de clone die de run toch al heeft, nadat een pull request in de standaardbranch is gemerged, elke nacht als de branch is veranderd, en wanneer iemand op Vernieuwen drukt. Voor regels is dat belangrijk: een controle tegen het diagram van vorig kwartaal is een controle tegen fictie.

Dan regels die je opschrijft

Op het tabblad Architectuur benoem je je componenten als paden, zoals API, Domain en Persistence, en geef je aan welke niet van welke afhankelijk mogen zijn: het domein importeert niet uit de databaselaag, de webapp grijpt niet in de worker. Een regel kan een toelichting krijgen die uitlegt waarom, en die toelichting reist met de regel mee.

Alleen een beheerder van de organisatie of de eigenaar van het project kan ze wijzigen, en elke wijziging staat in het auditlog. Regels die elk lid kan versoepelen om een run erdoor te krijgen, zijn geen regels.

Wat een run ermee doet

De componenten en architectuurregels gaan mee in de instructies van de agent voordat hij iets schrijft, samen met de huidige afhankelijkheden tussen componenten. Dat alleen voorkomt al een deel van de kortere wegen. Niet allemaal, en daarom zijn de instructies niet de controle.

De controle komt nadat de code is geschreven. De run brengt de gewijzigde bestanden opnieuw in kaart en vergelijkt het resultaat met de kaart van voordat de agent begon. Waar hij naar zoekt, is bewust smal: afhankelijkheden die deze wijziging heeft toegevoegd en die een regel verbiedt. Schendingen die al in je code zaten, zijn niet de schuld van de run. Een kleine bugfix laten falen omdat de codebase twee jaar geleden een regel brak, leert iedereen vooral om de controle uit te zetten.

Elke repository kiest een van drie standen:

  • Herstellen, de standaard. Een nieuwe schending gaat terug naar de agent, met de exacte imports die welke regel breken en de opdracht om te herstructureren: de code verplaatsen naar het component dat hem mag bevatten, afhangen van een abstractie, of de waarde van de aanroeper laten meegeven. Niet de feature schrappen, code kopiëren om de import te ontwijken of de import in een functie verstoppen. Heeft het project een verify-commando, dan draait dat na elke poging opnieuw, en het aantal pogingen is begrensd.
  • Melden. Geen herstelpogingen; schendingen staan in de pull request, zodat iemand ze kan beoordelen.
  • Uit. De kaart wordt nog steeds bijgewerkt, er wordt niets gecontroleerd.

Iteraties op een openstaande pull request worden op dezelfde manier gecontroleerd, tegen de doelbranch, zodat de controle de hele pull request dekt en niet alleen de laatste commit. Overleeft een schending een iteratie, dan komt hij als reactie op de pull request. Op een self-hosted runner stuurt de runner alleen de bronbestanden die zijn agent heeft gewijzigd voor de controle, nooit de hele repository.

De controle laat de run nooit falen

Dat is een bewuste keuze, dezelfde als bij de review- en securitycontroles. Een kapotte build hoort een run te stoppen. Een verboden import die twee herstelpogingen niet weg kregen, betekent meestal dat de taak zelf een grens overschrijdt, en dat is een ontwerpbeslissing voor een mens, geen reden om werkende code weg te gooien. Wat overblijft, staat duidelijk in de pull request onder "Architecture rules broken by this change", met het bestand dat importeert en het bestand dat het importeert.

Structuurwijzigingen in elke pull request

Elke pull request die een run opent, krijgt een sectie Structure changes, ook als er geen regel is gebroken: toegevoegde en verwijderde bestanden, nieuwe declaraties, nieuwe afhankelijkheden tussen componenten (of tussen mappen op het hoogste niveau, als je nog geen componenten hebt benoemd), nieuwe externe packages, en bestaande schendingen die de wijziging toevallig oplost. Declaraties in testbestanden laten we weg: een nieuwe testfunctie is geen nieuw onderdeel van het systeem.

Het beantwoordt de vraag die een reviewer echt heeft bij een grote diff: is de vorm van het systeem veranderd? Meestal niet, en dan is de sectie twee regels. Als het wel zo is, lees je die sectie als eerste.

Wat hij niet ziet

De kaart is gebouwd uit imports en declaraties zoals ze er staan. Dependency injection, reflection en dynamische aanroepen ziet hij niet, dus een regel kan tijdens runtime gebroken worden zonder dat de controle het merkt. Regels gaan over welk component van welk component afhankelijk mag zijn; iets als "elke handler moet idempotent zijn" leg je er niet mee vast. Dat hoort nog steeds in je conventies en in de review.

Waar je begint

Schrijf de ene regel op die je team in reviews al steeds herhaalt, meestal een variant van "het domein raakt de database niet aan", en zet hem eerst op melden. Een week aan pull requests laat zien of de controle klopt voordat hij werk terugstuurt. Op de pagina over de architectuurkaart zie je de weergaven, en de andere controles die een run doorloopt, beschreven we in vier controles vóór een AI-pull request.

Terug naar alle artikelen

Test het op een taak uit je eigen backlog

Stuur ons één echte taak. Wij draaien CodeLynq op jouw repository en jij reviewt de pull request. Gratis, binnen 5 werkdagen.