Analyze
Facts and evidence
How Brunel turns a repository into facts, each with a confidence and the file and lines that prove it, and how to correct a fact that is wrong.
Why facts
A design is only as good as what it is based on. Brunel does not ask a model to guess what your code does: 16 deterministic detectors read the files and emit facts, and every fact carries its evidence. The design then cites the facts that justify each component, so you can trace any decision back to a line of your repository.
Anatomy of a fact
{
"id": "f_db_postgres",
"category": "datastore",
"key": "postgres",
"value": "16",
"confidence": 0.95,
"evidence": [
{ "path": "docker-compose.yml", "lines": [12, 14], "snippet": "image: postgres:16-alpine" },
{ "path": "package.json", "lines": [21, 21], "snippet": "\"pg\": \"^8.11.3\"" }
],
"source": "detector"
}| Category | What it covers |
|---|---|
language | Languages by share of code |
framework | Web frameworks and app frameworks |
runtime | Node.js, Python, Go, JVM, PHP, Ruby, Rust, Bun… and their versions |
datastore | Relational and document databases, search engines, object storage |
middleware | Caches, queues, streams, reverse proxies |
workload | Web processes, workers, cron jobs, websockets, release commands |
integration | Payments, email, SMS, AI services, authentication, Slack… |
env | Environment variable names (never values) and what they imply |
container | Dockerfiles: base image, ports, multi-stage builds, user |
ci | Existing CI and whether tests run |
existing-infra | Where the app runs today: Terraform, Kubernetes, Helm, Vercel, Heroku, Fly, Render, Railway… |
scale-hint | Signals of size: monorepo, number of models, migrations… |
Confidence
Each rule has a confidence between 0 and 1. A dependency named exactly like a framework's server package is strong evidence; a generic name is weaker. When several detectors find the same thing, their evidence is merged into one fact and the confidence is the highest one.
Secrets never become facts
Environment files give names only: DATABASE_URL tells Brunel you use a relational database, S3_BUCKET object storage, SMTP_HOST email. Values are never read into facts. Secret-looking values are redacted from every stored excerpt and from anything the AI sees.
Correct a fact
Every fact can be corrected in the analysis view. A fact you set has source: "user" and wins over detection: re-analyses keep it, and the design uses it. Removing a wrong fact removes the components it justified at the next design.
From facts to services
The facts feed the identification of services: what gets deployed, with its type (web-ssr, spa, api, worker, cron, websocket, static), runtime, port and whether it keeps state. Things Brunel could not determine are listed as unknowns, never invented.
See What Brunel detects for the complete list of recognized packages.