Facet

Measuring code quality with AI is harder than it looks.

Every coding tool ships with an AI reviewer now. A model reads your code, tells you what is wrong, and you ship faster. The promise is fast feedback at human-reviewer quality with the convenience of an inline comment.

The reality, increasingly well-documented in the research literature, is that the underlying measurement is usually not reliable. Validity is reported even less often, and reproducibility on real code almost never. Facet is one product in this category. We wrote it because the measurement problem is solvable if you treat it as a measurement problem and not as a prompt-engineering one. This page is the background for the methodology that follows.

Two stylised quality fingerprints, side by side. The same problem; two distinct profiles.

The pitch you have already seen

In the standard LLM-as-judge setup a foundation model reads a file or a diff and returns a paragraph, a score, or a pass/fail. The model decides what counts, and how much it counts, and the product trusts that judgement.

This works when the model is right. The literature suggests the model is often not right, and the marketing rarely says so. Four mechanisms keep this category quietly unreliable.

One. The judge believes its own reading of the code

A function called sanitize_inputthat does not sanitise reads as a sanitiser to a judge looking at code. The name does the work the code does not. The same surface-form sensitivity that lets a model be fooled by reassuring documentation gets it fooled by reassuring identifiers, function shapes, and helpful-looking comments. The standard fix is “prompt the model better”. This usually nudges the failure mode rather than removing it.

Facet’s answer is structural, not prompt-level. The judge cannot grade. It extracts atomic features with a one-clause basis and a line citation, and deterministic code computes the score from those features. A function name is a claim. A claim without cited evidence is absent. The opinion lives in version-controlled, deterministic logic, not in a model output.

The find / decide split. Your code through a judge (model, extracts features and line citations) into a score (deterministic code computes the 14-dim level).

Two. One judge for all the dimensions

Code quality is not one thing. Performance, security, readability, and audit trail are different questions that need different evidence. Picking one frontier model to grade all of them is a convenience, not a finding.

When we qualified judges per construct on the 14-dimension rubric, no single model came out on top everywhere. The judge with the highest overall agreement on one construct failed the minority-recall gate on another; a different open-weight judge caught the rare class there but ran weaker elsewhere. Different judges win different constructs in the production routing. Facet routes each dimension to the judge that earned the right to score it.

Three. Agreement without minority-class recall is the wrong number

The standard reliability number for LLM judges is agreement with a reference set. A judge that says “looks fine” to every healthy file is right most of the time because most files are healthy. The number looks great. The judge has caught nothing.

The criterion that bites is minority-class recall. Of the genuinely broken cases, how many did the judge catch? Facet’s reliability gate enforces it at ≥ 0.50 on every dimension. It has rejected high-agreement judges in favour of lower-agreement, higher-recall ones more than once. The label means something because the threshold is documented and the rejection is real.

Four. Temperature zero is not deterministic

The same code submitted twice can produce different scores. Provider routing, hidden quantisation differences between backends, and silent model updates all push this. Even at temperature 0 with the same seed, different backends of nominally the same model give different greedy outputs.

We measured the drift on real code and shipped four levers to tame it. A single pinned provider per call. A fixed seed. A chunked feature list when a long prompt diluted per-feature attention. An N-vote ensemble on the noisier dimensions. The label “reliable” on a Facet dimension requires a real-code feature-stability of at least 0.90 across re-runs. The instrument is allowed to drift. The claim attached to it is not.

What the research literature actually says

The marketing claims and the academic findings have diverged. A brief tour, in case you want to read source. The foundational work is well-known, but the 2025 and 2026 papers are where the field has moved to actually quantifying how unreliable the standard setups are.

The foundations from 2023 and 2024.

What 2025 added.

None of these papers say LLM-as-judge cannot work. They say it is harder than the marketing claims, the failure modes are specific and addressable, and the right response is measurement discipline rather than a louder model.

What Facet does differently. Measurement discipline, not a model upgrade

We treat the rubric as a psychometric instrument and ask it to pass instrument-grade tests. The pieces.

  • Find then decide. The model never assigns a score. It extracts atomic features with a present, absent, or not-applicable status and a one-clause basis. Deterministic code does the scoring. The opinion lives in deterministic, version-controlled logic.
  • Claims are not evidence. Reassuring names, comments, and docstrings are claims. Without cited line-level evidence, a claim is absent. This is the structural defence against the most common failure mode in the category.
  • Four-bar reliability gate per dimension.Schema coverage ≥ 0.80, surface-weighted agreement ≥ 0.60, minority-class recall ≥ 0.50, and test-retest reproducibility ≥ 0.90. Documented, enforced, and the criterion that rejects high-agreement judges with poor minority-recall.
  • Per-construct routing. Each of the 14 dimensions runs against the judge that earned the right to score it. Five different open-weight judges win five different constructs in the data.
  • Formative scoring, fitted to evidence. A within-dimension unidimensionality test on a 47-file real-code corpus showed 13 of 14 dimensions are formative composites, meaning features that constitute the construct rather than reflect a single latent trait. A cumulative Guttman ladder over independent features mis-scores. A graded-response IRT model assumes the very unidimensionality the data deny. We use compensatory counting for the 13 and cumulative for the one dimension where the data supports it.
Reflective vs formative measurement model. Reflective shows a single trait causing its indicators (arrows out). Formative shows indicators constituting the construct (arrows in).
  • Two sub-scores per dimension. Capability (positive indicators present) and violation (negative-polarity indicators present), reported separately. A feature-rich-but-vulnerable file and a minimal-but-clean file are different things and do not collapse to one number.
  • Determinism levers.Provider-pinned calls, fixed seed, chunked extraction on long prompts, and an N-vote ensemble on the noisier judges. The label “reliable” requires real-code feature-stability of at least 0.90, not temperature-0 hope.

The full per-dimension evidence and the Lane A construct-validity results live on the methodology page. To watch the whole discipline applied end-to-end to a single dimension, external weights, adversarial self-review and all, read the Security worked example.

What we do not claim

  • Construct validity is partial.Lane A (exploratory, single open-weight judge, N ≈ 47 to 50 real files) is complete. No inter-dimension pair |r| ≥ 0.70. Roughly 6 weakly-correlated factors with no general-quality halo. 4 of 4 known-groups discrimination on the dimensions whose absolute level was least certain. Lane B confirmatory work with a second independent judge, a larger held-out corpus, formal inter-rater κ, and formal DIF across languages is in progress.
  • One judge per dimension is still a simplification. Ensemble extraction on the noisier dimensions partly mitigates run noise. It does not give us cross-judge convergent validity. That is on the Lane B list.
  • Functional correctness is scoped out. Facet measures how code is written, not whether it computes the right answer. Broken code with the right machinery can still score well on the structural dimensions. We say this plainly rather than pretend the rubric covers it.
  • The predicates are not published. The exact indicator predicates and per-feature criteria do not appear on the methodology page or in this article. The rubric is the product. Third parties can audit it under collaboration agreement.

The honesty frame

AI-powered insights without measurement discipline is a confident model. With measurement discipline, you get an instrument a skeptic can test. The gap between the two is not a better foundation model. It is the work the category has mostly not done.

The full evidence and per-dimension data live on the methodology page. The thesis in action is on the demo page, where the same small problem is solved several ways and profiled by the live engine. None is best on every axis. That is what a profile, not a score, means.

Profile your codeRead the methodology