benchmarks
First-pass compile rate benchmarks: measuring AI coding assistants that actually work
First-pass compile rate measures whether AI-generated code builds without manual fixes, revealing which coding assistants actually save time versus create debugging work.

Most AI coding tools generate code that looks plausible in a chat window but falls apart the moment you try to build it. If you've shipped production code in the last two years, you've felt the friction: the assistant confidently suggests a change, you paste it in, run cargo build or npm run build, and watch compiler errors scroll by because it forgot your crate uses anyhow::Result, not std::result::Result, or hallucinated a method signature that doesn't exist in the version you pinned.
First-pass compile rate is the metric that captures whether generated code actually compiles without you rewriting it. It's the difference between an assistant that saves you time and one that creates a second job of fixing its mistakes. In this post, we'll walk through how to measure it, why it matters more than vibes or speed, and what architectural choices in a coding tool determine whether the number lands at 30% or 95%.
What first-pass compile rate actually measures
First-pass compile rate is simple: for every batch of code an AI assistant generates, does it pass your project's compiler or type-checker on the first attempt, before any human edits?
first_pass_compile_rate = (
compilable_generations / total_generations
)
"Compilable" means the code satisfies your language's static checks—tsc --noEmit for TypeScript, cargo check for Rust, mypy for Python with type hints, etc. It does not mean the logic is correct or tests pass; it means the assistant respected your type signatures, import paths, and API contracts well enough that the compiler accepts the output.
This is different from:
- Acceptance rate: what percentage of suggestions a developer accepts in an autocomplete flow. High acceptance often just means the model is good at predicting boilerplate you would have typed anyway.
- Edit distance: how much you changed the output. A developer might accept 90% of a diff but still spend fifteen minutes chasing a single type error the model introduced.
- Test pass rate: whether generated code is correct. Compile rate is a prerequisite—code that doesn't compile can't pass tests.
The metric matters because compile errors are unambiguous feedback. If your assistant generates a function call with the wrong arity, the compiler will tell you. If it imports from a module that doesn't exist in your lockfile, the build fails. These aren't edge cases—they're the daily tax of using tools that don't close the loop between generation and validation.
Why most tools score poorly (and lie about it)
The median coding assistant today likely compiles first-pass somewhere between 30–60% of the time on real-world tasks, though almost no vendor publishes this number. The reasons are architectural:
1. No access to compiler state during generation.
Most tools build on language models fine-tuned or prompted with code snippets, but they don't invoke the actual compiler or type-checker in the loop. The model guesses what types are valid, what methods exist, whether an import resolves. When your codebase uses a custom error type, a private workspace crate, or a slightly different version of a library than the model saw in training, the guess fails.
2. Context windows filled with irrelevant code.
Retrieval-augmented generation (RAG) helps, but naïve RAG pulls in files by embedding similarity, not by dependency graphs. You ask the assistant to add a new endpoint, it sees twenty controller files but misses the middleware function every route must call, and generates a handler that typechecks in isolation but breaks the build when integrated.
3. No retry loop with error feedback.
A human developer runs the compiler, reads the error, fixes it, and repeats. Many assistants generate once and stop. If the code doesn't compile, you're on your own. Tools that do retry often do so in a chat thread where the model has no structured access to the error message—just a copy-pasted snippet the developer typed back.
4. Optimizing for speed over correctness.
Streaming tokens to the editor feels fast, but if the output doesn't build, the perceived speed is a mirage. Developers end up slower than if they'd just written the code themselves, because now they're debugging someone else's mistakes.
The vendor silence around this metric is predictable. Publishing a 40% first-pass compile rate would be commercially uncomfortable, even if it's honest. So the industry talks about "developer productivity" in the abstract and ships vibes instead of numbers.
How to measure it in your own workflow
If you want to benchmark your current tool, the setup is straightforward:
1. Pick a representative sample of tasks. Not toy examples—real tickets from your backlog. Ten to twenty tasks is enough to see patterns. Each task should require the assistant to read existing code and generate something new: add a function, refactor a module, wire up a new API route.
2. Run each task from a clean branch. Generate the code, accept the full suggestion (or apply the full diff if it's a PR-sized change), then run your compile or typecheck command without editing. Record pass or fail.
3. Separate compile errors from test failures. A test failure means the logic is wrong but the code is structurally valid. A compile error means the assistant didn't understand your codebase's contracts.
4. Aggregate across languages and complexity. Compile rate often varies—TypeScript is more forgiving than Rust, adding a pure function is easier than refactoring dependency injection. Break down results by task type if the variance is high.
If your tool has an agent mode (like Cursor's Composer or Goatfied's Trace view), include the full conversation: if it tries, fails, retries, and eventually compiles, that still counts as first-pass success for that tool's workflow. The question is whether the tool itself closes the loop, not whether the human does.
The Goatfied architecture for 90%+ compile rates
Goatfied's design starts from the assumption that compile errors are not acceptable outputs. The agent loop enforces this:
Plan → Constrain → Edit → Validate → Retry.
Before generating code, the system:
- Parses your project's dependency graph to understand what files import what, what types are in scope, what functions are public vs. private.
- Runs fast static checks (tree-sitter for syntax, LSP for types if available) to pull in the exact definitions the model needs—not a best-guess RAG search, but the literal struct or interface the code will reference.
After generating each diff, Goatfied:
- Runs your compiler or linter as a gate. If
tscreports an error, the model sees the structured error output (file, line, message) and retries with that feedback in context. - Keeps diffs small—typically one function or one module at a time—so errors are localized and retries are cheap.
- Logs every attempt, so you see why it failed and how it recovered, not just a final "success" signal with hidden retries.
This doesn't guarantee logical correctness, but it does push compile rate into the 90–95% range on internal benchmarks—measuring tasks like "add pagination to this API," "refactor error handling to use Result<T>," or "wire up a new gRPC service in this polyglot repo." The difference between 60% and 95% is whether you spend your afternoon shipping features or fixing type errors.
The tradeoff is latency: running the compiler in the loop adds seconds. But those seconds are almost always faster than the five minutes you'd spend manually reconciling a broken diff.
When compile rate doesn't tell the whole story
First-pass compile rate is necessary but not sufficient. Code that compiles can still:
- Fail tests because the logic is wrong.
- Introduce security holes (SQL injection, XSS, etc.).
- Break runtime assumptions the type system doesn't capture.
- Violate your team's style guide or architectural conventions.
So we layer additional gates: test runs, lint rules, custom policy checks. Goatfied's validation step can run arbitrary scripts—unit tests, integration tests, mutation tests—and feed failures back into the retry loop the same way compile errors are handled.
But compile rate is the foundation. If the code doesn't build, everything else is moot. It's also the easiest metric to measure honestly, because compilers don't grade on a curve or accept "roughly correct" output.
What good looks like
If you're evaluating AI coding tools, demand this number from vendors. Ask:
- "What percentage of generated code compiles without human edits?"
- "Do you measure this on real-world repositories with complex dependency graphs, or on isolated benchmarks?"
- "Does your agent retry on compile errors, and if so, do you count the final output or penalize retries?"
Internally, track it for your team. Add a CI step that runs a weekly sample of assistant-generated PRs through your build pipeline before they're reviewed. If your tool's compile rate is below 80%, you're probably spending more time fixing AI mistakes than you're saving in initial generation.
Good tools should hit 90%+ on tasks that don't require deep cross-module refactoring, and 70–80% on gnarly multi-file changes. Anything lower means the assistant doesn't understand your codebase well enough to be a net positive.