Code is the easiest output to evaluate — and the hardest
Easy because you can run it; hard because "the code runs" is necessary but not sufficient. A passing test does not mean the code is good. Three quality layers matter.
Layer 1: execution correctness
Runs the generated code; checks against unit tests. pass@k is the fraction of attempts where ALL tests pass on at least one of k samples. This is what HumanEval and SWE-bench measure.
Layer 2: code quality
- Static analysis — linters, type checkers, security scanners (bandit, semgrep).
- Style — ruff, prettier, black. Doesn't catch bugs but signals "would a human accept this PR?"
- Complexity — cyclomatic, nesting depth.
- Documentation — docstrings, comments, type annotations.
Layer 3: behavioral correctness beyond the test
The generated code passes its tests but does it match the intent? An LLM judge can compare implementation against the natural-language spec. This is where most "looks correct, isn't" bugs hide.
Code-specific safety checks
Generated code can have command injection, SQL injection, hardcoded secrets, unsafe deserialization, or insecure dependencies. A security scanner (semgrep, bandit, npm audit) on the generated code is part of the eval, not an afterthought.