# Doctrine

Award scores craft. It exists because a scoring system that is allowed to move its
own bar will always report success, and this repo has three recorded instances of
exactly that.

These are not style preferences. Each one is a bug that shipped, and each has a
test that fails if the guard is removed.

## 1. Never tune a threshold to make a run pass

Fix the work, not the bar. A quality scalar under optimisation pressure gets gamed.
The previous refiner triggered on `axes.materials < 62` and answered with light
energy: the score rose while measured contrast fell.

Gates may be optimised; quality scores may not. Clearing a gate and being correct
are the same state — that is what makes a gate safe to chase. A score is a
judgement, and chasing a judgement is how you learn to flatter yourself.

## 2. Tests must recompute

Never assert over a recorded `EVAL.json`. Both sides of that comparison come from
the same file, so it proves the file is equal to itself. Fixtures go in, scores
come out, the test compares the output to an independent expectation.

## 3. A set of your own work can never certify itself

The gold set had been all-approve, which made its 100% alignment the score a critic
gets for passing everything. Calibration requires **separation** as well as
alignment, and at least one entry the studio did not produce (`anchor: 'external'`).

Without an external anchor, separation only proves the critic agrees with your own
ranking. It cannot detect that the whole set sits too low. The object set is
deliberately not ready for this reason, and says so.

## 4. Calibrate against the medium you are judging

Two rubrics, sharing no axis. This was learned twice, from opposite directions.

Page anchors were first scored with a product-photography rubric and the ranking
inverted — linear.app came last for being typographic. Then object review repeated
it in reverse: six judges across three rounds, each calibrated against screenshots
of *web pages*. Their individual findings were specific and correct every time, and
the bar never moved — part count went 11 → 13 → 20 while `manufacturingLogic` read
45, 45, 42, 32, 48, 45.

Real findings and no stable bar is the signature of a miscalibrated reference.

## 5. Refuse rather than guess

A page with no page-craft axes is unscored, not zero-scored. A medium with no judge
reachable refuses instead of falling back to contrast and occupancy. A measurement
backend that is missing raises `MEASUREMENT_UNAVAILABLE` instead of estimating.

A critic that always returns a number is indistinguishable from one that is working.

## 6. Match the critic's resolution to the defect's scale

Page-level review spends about one paragraph on geometry and sees the subject at
roughly 300px. One wrist assembly survived three page rounds at 63/58/63. The first
time the object was rendered alone and judged on its own terms, the review found a
functional error in one line: the pitch axis carried nothing, because the clevis
cheeks were parented to the rotating group.

## 7. Verify the instrument before trusting the reading

Four separate bugs in one capture harness each produced an invalid judgement — a
crop that cut the subject out of every frame, a bump strength of 0.0016 that made a
texture invisible, an error handler attached after navigation that reported "0
errors" on a blank page, and a key light at 2200W that blew every surface white and
earned the object a 28 for being "untextured".

The harness was less reliable than the thing it measured. Check it first.

## Provider independence

Vision is vendor-agnostic and falls through on failure: Claude, Gemini, GPT, Grok,
plus keyless paths. One vendor's billing state must never decide whether a critic
can work.
