Farol: Ken het risico van het mergen van een pull request

De rol van Farol in het reviewproces

Agents schrijven de code en agents reviewen deze, maar de uiteindelijke beslissing om een merge goed te keuren blijft een menselijke taak. Wanneer die aandacht gelijkmatig over elke pull request wordt verdeeld, verandert de review vaak in een oppervlakkige scan. Dit kan ertoe leiden dat een wijziging van één regel in een gedeelde hook veertig pagina's platlegt.

Farol is bedoeld als aanvulling op, niet als vervanging van, de AI-review. Waar een review-agent commentaren plaatst bij regels in de diff, biedt Farol de reviewer informatie die een agent niet betrouwbaar kan geven: het risico van het accepteren van de wijziging en waar dit risico zich bevindt.

Het doel is niet alleen een snellere review; pull requests met een laag risico kunnen snel worden afgehandeld, terwijl risicovolle wijzigingen regel voor regel worden gelezen, beginnend bij de meest kritieke bestanden. Farol maakt gebruik van statische analyse (het perspectief van de compilers op de code, niet de gok van een model), waardoor dezelfde pull request altijd hetzelfde resultaat geeft.

Vergelijking: AI-review agents versus Farol

KenmerkAI-review agentsFarol
AnalyseLeest de diff en de context die in de prompt pastLeest het volledige programma (basis en head) met compilers (TypeScript type checker, go/types, Python ast)
OutputVertelt wat er mogelijk mis is in specifieke regelsVertelt wat deze regels bereiken, hoe riskant de merge is en waar eerst te kijken
Aard van antwoordenProbabilistisch: woorden verschillen per runDeterministisch: dezelfde PR geeft hetzelfde rapport; elke claim bevat een call-chain
OnzekerheidKan zelfverzekerd klinken, zelfs bij onzekerheidGeeft "unknown" aan en vraagt om een zorgvuldige review
UitvoeringDraait een model, meestal via een hosted serviceDraait lokaal of in CI; voert nooit code uit en verzendt deze nergens heen

Advies: Gebruik beide in deze volgorde. Laat de agent eerst de regels reviewen; daarna vertelt Farol de reviewer hoeveel aandacht de merge nodig heeft, welke bestanden prioritair zijn, welke pagina's en endpoints handmatig getest moeten worden en welke contractwijzigingen gecontroleerd moeten worden bij de clients.

Waarom Farol?

  • Focus op risico: Review-aandacht gaat naar waar het risico zit. Een PR van 40 bestanden bevat vaak slechts twee of drie bestanden die echt schade kunnen aanrichten. Farol rangschikt deze, zodat de reviewer die nauwkeurig leest en de rest met een gerust hart scant.
  • Volgt de code, niet de bestandsnamen: Farol bouwt een declaratiegrafiek met echte compilers. Een wijziging in formatPrice toont de twaalf pagina's die deze functie renderen, in plaats van simpelweg "1 bestand gewijzigd".
  • Detectie van contractbreuken: Contractbreuken worden gevangen voordat de clients dat doen. Dit geldt voor verwijderde response-velden, nieuwe verplichte parameters en gewijzigde types in GraphQL, FastAPI, Go handlers en gRPC.
  • Incrementele reviews: Elke push genereert twee rapporten: één voor de volledige pull request en één voor alleen de commits sinds de vorige push. De reviewer hoeft na een ronde fixes niet opnieuw te beginnen.
  • Integratie met bestaande CI: Coverage, lint- en security-rapporten worden omgezet in diff-coverage en bevindingen op de gewijzigde regels. Niets wordt dubbel uitgevoerd.
  • Fail closed: Wanneer Farol een deel van een wijziging niet kan lezen, wordt dit als "unknown" gemarkeerd en wordt er gevraagd om een zorgvuldige review. Het labelt iets nooit als veilig als het de code niet begrijpt.
  • Ontworpen voor de mens: Reviewers kunnen bestanden markeren als gereviewd, pagina's als zijnde achter een feature flag plaatsen en bevindingen afvinken.

Aan de slag

Vereisten

  • Node.js 22+ en git.
  • Voor Go-projecten is Go vereist.
  • Voor Python-projecten is Python 3.11+ vereist.

Je kunt Farol direct uitvoeren zonder installatie via: npx @winninjs/farol.

Installatie en gebruik

  1. Projectbeschrijving: Maak een farol.config.json aan in de root van je project. Kies de configuratie die past bij jouw stack:
  • React app met React Router: { "routes": { "file": "src/routes.tsx" } }
  • Next.js app (Pages of App Router): { "routes": { "adapter": "next" } }
  • React app met TanStack Router: { "routes": { "adapter": "tanstack-router", "dir": "src/routes" } }
  • TypeScript API (GraphQL, REST): { "surface": "backend" }
  • Go service: { "language": "go", "surface": "backend" }
  • Python service (FastAPI, Flask, Django, Celery…): { "language": "python", "surface": "backend" }
  1. Controleer de weergave: Kijk welke pagina's, endpoints, jobs en scripts Farol heeft gevonden:

npx @winninjs/farol routes

  1. Analyseer en rapporteer: Analyseer een branch ten opzichte van het doel en open het rapport:

npx @winninjs/farol analyze --base origin/main --head HEAD --out farol.json npx @winninjs/farol html --in farol.json --out farol.html && open farol.html

Voorbeeld: React app met React Router

cd path/to/your/react-app
echo '{ "routes": { "file": "src/routes.tsx" } }' > farol.config.json
npx @winninjs/farol routes
git checkout my-feature-branch
npx @winninjs/farol analyze --base origin/main --head HEAD --out farol.json
npx @winninjs/farol html --in farol.json --out farol.html && open farol.html

Recepten per stack

Elk recept bestaat uit de farol.config.json, de te produceren rapporten en de GitHub Actions workflow.

React frontend (React Router)

  • Configuratie:

``json { "routes": { "file": "src/routes.tsx" }, "roles": { "global": ["src/main.tsx", "src/App.tsx", "src/styles/global.css", "package.json", "vite.config.ts"] } } ``

  • Rapporten:
  • Coverage: npx vitest run --coverage.enabled --coverage.reporter=json --coverage.reportsDirectory=reports/coverage
  • Lint: npx eslint -f json -o reports/eslint.json <changed files>
  • Audit: npm audit --json > reports/audit.json
  • Analyse:

npx @winninjs/farol analyze --base origin/main --head HEAD --coverage reports/coverage/coverage-final.json --eslint reports/eslint.json --audit reports/audit.json --out farol.json

Next.js

Ondersteunt Pages Router en App Router.

  • Configuratie:

``json { "routes": { "adapter": "next" }, "roles": { "global": ["next.config.*", "package.json"] } } ``

  • Rapporten en CI: Gelijk aan React Router (Jest of Vitest coverage, ESLint, audit).

TanStack Router

Ondersteunt file-based routing.

  • Configuratie: { "routes": { "adapter": "tanstack-router", "dir": "src/routes" } }
  • Rapporten en CI: Gelijk aan React Router.

TypeScript API (GraphQL of REST)

  • Configuratie:

``json { "surface": "backend", "backend": { "graphql": true, "rest": true }, "roles": { "global": ["package.json", "src/app.ts"] } } ``

  • Rapporten en CI: Gelijk aan React Router. Bij gebruik van injected context voor data-access, geef dan de providers aan via "backend": { "context": { "loaders": ["src/modules/*/loaders/index.ts"] } }.

Go service

  • Configuratie: { "language": "go", "surface": "backend" }
  • Rapporten:
  • Coverage: go test -coverpkg=./... -coverprofile=reports/cover.out ./...
  • Lint: golangci-lint run --output.json.path=reports/golangci.json --issues-exit-code=0 ./...
  • Security: govulncheck -json ./... > reports/govulncheck.json
  • Analyse:

npx @winninjs/farol analyze --base origin/main --head HEAD --coverage reports/cover.out --eslint reports/golangci.json --audit reports/govulncheck.json --out farol.json

Python service

  • Configuratie: { "language": "python", "surface": "backend", "python": { "roots": ["src", "."] } }
  • Rapporten:
  • Coverage: pytest --cov=src --cov-report=json:reports/coverage.json
  • Lint: ruff check --output-format json --extend-select S --exit-zero . > reports/ruff.json
  • Security: pip-audit --format json -o reports/pip-audit.json
  • Analyse:

npx @winninjs/farol analyze --base origin/main --head HEAD --coverage reports/coverage.json --eslint reports/ruff.json --audit reports/pip-audit.json --out farol.json

Datadog integratie (Optioneel)

Voegt informatie toe over verkeer en fouten in productie. Dit beïnvloedt de risicoscore niet.

  • Configuratie:

``json { "datadog": { "env": "prod", "rum": { "applicationId": "<RUM application id>" }, "apm": { "service": "orders-api", "operations": ["fastapi.request"] } } } ``

  • Gebruik:

DDAPIKEY=… DDAPPKEY=… npx @winninjs/farol usage --out usage.json npx @winninjs/farol analyze … --usage usage.json

Ondersteunde functies

KenmerkTS / React FrontendsTS / JS BackendsGoPython
Entry pointsReact Router, Next.js, TanStack RouterGraphQL, REST (Fastify/Express)chi, gin, echo, net/http, gRPC, binariesFastAPI, Flask, Django, MCP, Celery, Temporal, Prefect, \\main\\
Reach precisiePer declaratie (TS type checker)Per module, per resolver (GraphQL)Per declaratie (go/types)Per declaratie (Python ast)
Contractwijzigingen—GraphQL schemaHandler request/response types, gRPCFastAPI parameters, body, response, Pydantic
Dependenciespackage.json + lockfilesZelfdego.mod + go.sumpyproject.toml, requirements.txt + lockfiles
Diff coverageIstanbul (Vitest, Jest)Zelfdego test -coverprofilecoverage.py JSON (pytest)
Linteslint -f jsonZelfdegolangci-lint JSONruff JSON
SecurityIngebouwde regelsZelfdegosec (via golangci-lint)flake8-bandit (ruff S)
Vulnerabilitiesnpm/pnpm auditZelfdegovulncheckpip-audit
Suppressionseslint-disable, @ts-ignore...Zelfde//nolint, #nosec# noqa, # type: ignore...
Traffic/ErrorsDatadog RUMDatadog APMZelfdeZelfde

De review lezen

Farol produceert een PR-commentaar met het verdict en een HTML-rapport.

Verdict en risicoscore

De score (0–100) geeft de kans aan dat er minstens één risicovol item iets breekt.

VerdictBetekenisActie
✓ Fast trackAlleen nieuwe code, tests of lage risico's.Scan de diff en keur goed.
◐ Quick reviewBestaande code beperkt gewijzigd, of zwak signaal (lage coverage).Controleer "Start here" bestanden, keur dan goed.
⚠ Careful reviewBrede of sluipende breuken mogelijk (score 60+, contractbreuk, high-severity finding, ongelezen code).Lees "Start here" bestanden regel voor regel en test wat ze bereiken.

Onderdelen van het rapport

  • Start here: De gewijzigde bestanden, gesorteerd op risico. Toont bereik, diff-coverage en bevindingen.
  • Behind a feature flag: Markeer entry points die achter een vlag zitten. Deze worden uit de score gehaald omdat ze nog niet voor alle gebruikers live zijn.
  • Pages / Operations: Een lijst of boom van beïnvloede entry points. Toont de call-chain van de wijziging naar het endpoint.
  • Contracts (backends): Toont wijzigingen in endpoints als breaking (clients kunnen falen), dangerous (kunnen zich vreemd gedragen) of safe (compatibele toevoegingen).
  • Security, Dependencies, Coverage: De bewijslast achter de score: specifieke security findings, kwetsbare dependencies en coverage per bestand.
  • Test plan: Een handmatige checklist van pagina's of operaties om te testen, gesorteerd op risico.
  • Reviewers: Suggesties voor reviewers op basis van wie de code in de meest risicovolle bestanden heeft geschreven (git blame) en CODEOWNERS.
  • Result: Een Markdown-record van de review die in de PR kan worden geplakt als bewijs van wat er is gecontroleerd.
  • Since the last push: Een apart rapport voor alleen de nieuwe commits sinds de vorige push, zodat de reviewer niet opnieuw hoeft te beginnen.

Technische werking

  1. Diffing: Vergelijkt de merge-base en de head, detecteert renames en negeert whitespace/trailing commas.
  2. Statisch lezen: Leest beide trees zonder code uit te voeren via de TypeScript compiler API, go list + go/types, of Python ast.
  3. Vergelijking: Vergelijkt declaraties via een hash van de code (commentaren en formatting tellen niet mee).
  4. Reach analyse: Berekent vanaf elke gewijzigde declaratie de kortste keten naar elk entry point dat deze aanroept.
  5. Classificatie: Bepaalt de klasse, score, verdict, prioriteit van bestanden en het testplan.

Beveiliging en privacy

  • analyze voert nooit code uit van het geanalyseerde repository en gebruikt geen netwerk.
  • Alleen comment (GitHub API) en usage (Datadog API) communiceren met het netwerk.
  • In CI heeft de job die code uitvoert geen geheimen en geen write-token; de job die commentaart voert nooit code uit.
  • Shadow mode: Farol informeert alleen; het keurt nooit goed, vraagt niet om wijzigingen en blokkeert nooit een check.

Beperkingen

  • Statisch lezen: Waarden die tijdens runtime worden gebouwd zijn onzichtbaar (bijv. computed route paths, getattr, DI containers).
  • TypeScript frontends: Alleen React Router, Next.js en TanStack Router (file-based). Geen Vue of Svelte.
  • Go: Route-prefixes van middleware stacks (behalve chi/gin/echo groepen) worden niet toegepast.
  • Python: Django REST Framework routers worden niet gelezen.
  • Heuristieken: De score- en verdictdrempels zijn heuristieken; kalibratie op eigen repositories wordt aangeraden via farol calibrate.

Veelgestelde vragen (FAQ)

We hebben al een AI-reviewer. Waarom Farol toevoegen? Ze beantwoorden verschillende vragen. De agent commentaart op regels in de diff; Farol vertelt de reviewer hoe riskant de merge is en welke bestanden het risico dragen op basis van de volledige programmastructuur.

Is het gratis? Ja. Farol is open source onder de MIT-licentie. Er is geen account, hosted service of betaald abonnement nodig.

Vertraagt het de CI? Nee. Farol draait na de tests en hergebruikt hun rapporten. De analyse duurt doorgaans enkele seconden.

Kan ik het buiten GitHub gebruiken? Ja. analyze, html en report werken overal. Alleen comment is specifiek voor GitHub.