Iedereen kan tegenwoordig laten zien dat een AI code schrijft. Dat is geen bewijs van iets. De interessante vraag is hoe — welke stappen, welke controles, en wat er gebeurt als het misgaat.

Deze pagina is het antwoord daarop, zonder illustraties. Hieronder staan de daadwerkelijke stappen die Spoor volgt, één echte reparatie van melding tot productie met de echte tijdstempels erbij, de gewoontes die het controleerbaar houden, en het aantal regels code dat er uit is gekomen. Alles op deze pagina is uit onze eigen systemen gehaald.

De pijplijn

Er zit geen mens aan een knop. Wat een taak in beweging zet is de combinatie van drie dingen in Linear: de status, het label, en aan wie hij is toegewezen. Klopt die combinatie niet, dan gebeurt er niets — niet later ook.

Trigger

Status + label + toegewezen persoon

Een issue in Linear met status Backlog, toegewezen aan Spoor, zonder het label Refined. check_backlog.py kijkt daar elke 5 minuten op — een gewone API-call, geen taalmodel, geen kosten. Is er niets nieuws, dan gebeurt er niets. Een issue dat aan een mens is toegewezen blijft liggen, hoe lang ook: er verloopt niets, niets claimt het alsnog.

  1. refine

    Herschrijft het issue tot een echte opdracht: probleemstelling, scope, acceptatiecriteria. Splitst het op in sub-issues als het te groot is, zet het label Refined erop en schuift het naar Todo.

    Waarborg Deze stap kan alleen bij Linear — geen bestanden, geen shell, geen git. Scope bepalen en code aanraken zijn hier fysiek van elkaar gescheiden.

  2. critique

    Een tweede blik op wat er net is opgeschreven: is de scope te groot, ontbreekt er een criterium, overlappen twee sub-issues, spreekt een label de tekst tegen?

    Waarborg Draait als een volledig nieuw proces met eigen context — niet dezelfde sessie die de tekst zelf schreef. En deze stap mag niets wijzigen: alleen commentaar plaatsen. Niets te melden hebben is een geldige uitkomst.

  3. resolve_critique

    Verwerkt die kritiek daadwerkelijk in het issue: opsplitsen, criteria aanscherpen, de echte afhankelijkheid vastleggen, een label rechtzetten.

    Waarborg Een formulering aanpassen is niet genoeg — het label of de afhankelijkheid zelf moet veranderen, want dát is wat de latere stappen afdwingen, niet de tekst. Het oneens zijn mag, maar dan expliciet en met reden; stilzwijgend negeren niet.

  4. implement

    Claimt eerst álle werkbare issues in één keer — naar In Progress, aan zichzelf toegewezen, zodat een gelijktijdige run niet hetzelfde issue nog eens oppakt. Werkt ze daarna parallel uit, één sub-agent per issue, draait de tests vóór de commit, en opent per issue een pull request.

    Waarborg Elke sub-agent werkt in zijn eigen geïsoleerde git-worktree, nooit in de kopie waar op dat moment een mens in kan zitten. En deze stap merget nooit zelf — dat is uitdrukkelijk aan de volgende.

  5. review_pr

    Leest de daadwerkelijke diff, op eigen merites. Repareert wat er mis is op diezelfde branch, merget (squash), ruimt de branch op en zet het issue op Done.

    Waarborg Opnieuw een apart proces met eigen context: niet dezelfde sessie die haar eigen werk nakijkt, en niet de samenvatting van wie de code schreef. Haalt de diff iets weg, dan wordt de hele repo doorzocht op verwijzingen naar dat weggehaalde ding — op de gewone naam ervan, niet alleen op de code-naam.

  6. deploy

    De merge naar main zet een deploy-workflow in gang op een runner op dezelfde VM: alleen de services die de wijziging raakt worden herbouwd en herstart. Daarna gaat er een bericht uit naar een mens.

    Waarborg Een groene deploy-run is geen bewijs dat er iets is uitgerold. Er wordt daarna nagegaan of die run ook echt deed wat er had moeten gebeuren — dat verschil heeft hier één keer daadwerkelijk gebeten.

Stap 1 tot 5 zijn letterlijk de bestanden refine.md, critique.md, resolve_critique.md, implement.md en review_pr.md in deze repo. Elke stap is een eigen proces met een eigen, verse context — geen lange sessie die zichzelf een cijfer geeft.

Liever kijken hoe dat er in de praktijk uitziet dan het hier lezen? De Spoor-wiki is een interactieve, geanimeerde sequence diagram van vijf echte gevallen — inclusief deze pijplijn, wie wat mag, en de harde stop-and-ask-lijst — met per stap een uitklapbare uitleg en tekst-selectie-naar-mailto.

Eén echte fix, van melding tot live

Op 7 augustus 2026 testte iemand van het team een nieuwe functie: één gebruiker doet iets, de pagina van een ander werkt zichzelf bij, zonder verversen. Het werkte — behalve dat diegene moest verversen. Precies het enige wat de functie moest oplossen.

  1. Iemand van het team meldt het via Telegram: de roundtrip werkt, maar hij moest de pagina van de host handmatig herladen om de klik van de gast te zien.

  2. Ontvangst bevestigd, 25 seconden later, met wat er nu gaat gebeuren. Geen ticket-nummer, geen wachtrij.

  3. Eerst reproduceren, dan pas code aanraken — tegen de echte productieomgeving, met een echte browsersessie en de echte inlogflow. Uitkomst: de server stuurde de update wél netjes door; de browser van de host had zich nooit aangemeld. Het scriptje dat die verbinding opzet gaf een 404, dus faalde de pagina stil vóórdat er iets kon meelezen. Een herlaadactie leek het te repareren, maar deed dat niet — die haalde de gegevens simpelweg opnieuw op.

  4. Issue PAI-334 aangemaakt in Linear, met de werkelijke oorzaak erin uitgeschreven: één verkeerd samengestelde padprefix tussen de reverse proxy en het framework, waardoor het bestand op de verkeerde plek werd gezocht. Precies één route in de hele applicatie was daar kwetsbaar voor — deze.

  5. Commit op een eigen branch, in een geïsoleerde werkkopie. Inclusief een test die de fout vastlegt: eerst aantoonbaar rood op de oude code, daarna groen op de fix.

  6. Pull request #294 geopend: 4 bestanden, +235 / −5 regels, met de reproductie en de verificatie in de beschrijving.

  7. Squash-merge naar main. Eén commit, één terugdraai-punt.

  8. De push zet de deploy-workflow in gang, op de runner op diezelfde VM. Twee seconden na de merge.

  9. Deploy klaar. 36 seconden. Alleen de geraakte service is herbouwd en herstart, de rest bleef ongemoeid draaien.

  10. Opnieuw getest in een echte browser, nu op de live site: gast klikt, de pagina van de host werkt zichzelf bij, geen herlaadactie. Dán pas een terugkoppeling naar de melder.

24 minuten en 36 seconden van melding tot terugkoppeling, inclusief het reproduceren, de test, de review en de deploy.

Twee dingen hierover, om het eerlijk te houden. Dit issue kwam niet via de pijplijn hierboven binnen maar via Telegram, en een melding van een mens is zijn eigen scope: de gebruikelijke planningsstap en de onafhankelijke tweede blik die normaal aan het werk voorafgaan (intern refine en critique genoemd) zijn hier dus overgeslagen. Dat is ook waarom er minuten tussen de stappen zitten en geen uren.

Wat níet is overgeslagen: eerst reproduceren en pas daarna code aanraken, een test die de fout vastlegt vóór de fix bestaat, en na de deploy opnieuw in een echte browser kijken of het er nu daadwerkelijk staat. De snelheid komt niet doordat er stappen zijn weggelaten.

En de oorzaak was, zoals bijna altijd, niet spectaculair: de laag die inkomend verkeer naar de juiste plek doorstuurt haalde een stukje van het adres weg, en de applicatie erachter plakte dat ongevraagd weer terug — waardoor één bestand werd gezocht op een plek waar het niet lag. Eén route in de hele applicatie was daar kwetsbaar voor. Die.

Hoe wij weten dat het klopt

Dit is het deel dat “wij gebruiken AI” onderscheidt van “wij laten AI ongesuperviseerd naar productie schrijven”. Het zijn geen beloftes; het zijn regels met een mechanisme erachter.

Een samenvatting is geen bewijs

“Klaar, tests groen” van het proces dat de code net zelf schreef, telt hier niet als verificatie. Er volgt altijd een aparte controlestap, in een nieuw proces met een eigen context, die de daadwerkelijke diff leest in plaats van die samenvatting. Niet dezelfde sessie die zichzelf een cijfer geeft.

Risicovol werk raakt nooit de gedeelde werkkopie

Elke geautomatiseerde taak werkt in zijn eigen geïsoleerde kopie van de code. Dat is een regel die wij op de harde manier hebben geleerd: één keer heeft een geautomatiseerde reparatie ingegrepen in de kopie waar op dat moment een mens aan het werk was, halverwege het samenvoegen van twee sets wijzigingen, en de code in een kapotte tussentoestand achtergelaten. Sindsdien is het geen goede intentie meer maar een mechanisme.

Bij twijfel komt er een vraag terug, geen gok

Er is een expliciete lijst van dingen die Spoor nooit zelfstandig doet, hoe routineus de rest van de taak ook is: een geforceerde push, branches, volumes of back-ups verwijderen, credentials roteren of intrekken, wijzigingen aan DNS of domeinen. Die gaan altijd eerst naar een mens. En stilte geldt niet als goedkeuring: waar een acceptatiecriterium expliciet op iemands akkoord wacht, is niets terughoren geen ja — en is het samenvoegen van de wijziging zelf ook geen ja.

Een groene deploy is geen bewijs dat er iets uitgerold is

Ook dit hebben wij op de harde manier geleerd. Er is hier een deploy geweest die netjes groen afsloot en “niets te doen” rapporteerde, terwijl de net samengevoegde wijziging nergens was herbouwd. Volgens zijn eigen logica volkomen correct — alleen geen deploy. Sindsdien wordt na elke samenvoeging van wijzigingen nagegaan of die run ook echt deed wat er had moeten gebeuren, niet of hij groen was.

Iets weghalen is niet klaar als de code weg is

Wanneer een functie of dienst wordt uitgezet, wordt alles waar de site en de systemen eromheen uit bestaan doorzocht op verwijzingen naar het weggehaalde ding — pagina’s, code, documentatie — op de gewone naam ervan, niet alleen op de technische naam waaronder het geïmplementeerd was. Dat onderscheid komt uit een echte fout: de code was verdwenen, de naam stond nog in een handvol documenten. Die naam gaat daarna in een register dat elke dag automatisch opnieuw wordt nagelopen, zonder taalmodel. Duikt de term ergens weer op, dan komt er een nieuw issue van.

En hoeveel code is dat dan?

Regels code toegevoegd 44.496

Opgeteld over alle 298 samengevoegde pull requests in deze repo, sinds 15 juli 2026.

7.346 regels verwijderd
985 bestandswijzigingen

Rechtstreeks uit GitHub gehaald tijdens het bouwen van deze pagina — geen schatting, geen handmatig bijgehouden getal. Laatste build: 07-08-2026.

Regels code is een grof getal — je kunt er alles en niets mee bewijzen. Wij zetten het er toch bij, om één reden: het is echt. Het wordt uit GitHub gehaald op het moment dat deze pagina wordt gebouwd, over de volledige samengevoegde werkgeschiedenis van Spoor tot nu toe, en er zit geen mens tussen die het bijhoudt of afrondt.

Wat het getal wél zegt: dit is geen proefopstelling die één keer iets indrukwekkends heeft gedaan. Het is de normale werksnelheid van deze opzet, over een paar weken heen, inclusief alle onvermijdelijke reparaties van het werk van de dag ervoor.

Verder lezen

  • Spoor-wiki — dezelfde keten, maar dan als interactieve, geanimeerde sequence diagram over vijf echte gevallen, met per stap een uitklapbare uitleg.
  • Werkwijze — dezelfde waarborgen, korter opgeschreven, bedoeld om intern door te sturen.
  • Case studies — concrete beslissingen uit onze eigen geschiedenis, en waarom we ze zo hebben gemaakt.
  • Productiviteit — dezelfde cijfers, breder uitgesplitst.

Wilt u dit in uw eigen bedrijf?

Neem contact op →