# Calibration rule

**Version 1. Dated 2026-09-09.**

This document is fixed. It is never edited. If it is found to be wrong, a new
version is written as a new document and applies only to cases issued after
that version's date. Cases are counted under the version in force when they
were issued.

This is a specification. It defines which stored cases enter the calibration
record, precisely enough that two parties working independently reach the same
count.

It governs `archive/calibration.json` only. It does not govern scoring, which
is `archive/SCORING_RULE.md`, and it changes no score.

---

## 1. What is counted

The calibration record counts **scoreable claims**, not stored cases.

> **A scoreable claim is one unique fit: one pair of `data_hash` and
> `as_of_effective`.**

Two cases carrying the same pair are the same fit. However many cases were
issued from it, they are one claim.

`data_hash` and `as_of_effective` are read from the case file. No other field
enters the identity: not `code_version`, not `issued_at`, not `kind`, not
`raw_input_hash`.

---

## 2. Which case counts

When more than one case shares a fit:

> **The case with the earliest `issued_at` is the one that counts.**

The others are **re-issues**. They are excluded from the calibration count.

### 2.1 Tie-break

If two cases sharing a fit carry an identical `issued_at`, the one whose
`case_id` sorts first as a byte string counts. This is deterministic and needs
no information outside the case files.

### 2.2 What exclusion does not mean

An excluded case is not deleted, not edited, not hidden and not unscorable.

- It remains in `archive/cases/` unchanged.
- It may be scored individually under `SCORING_RULE.md`, and its score is
  written and kept like any other.
- Its score is not counted in `calibration.json`.
- It is listed in `calibration.json` by id, with the case that supersedes it
  and the reason.

---

## 3. Rationale

Recorded because a count is only as trustworthy as the reason behind it.

**A re-issue under a new commit is not a new forecast.** The model said one
thing about one month on one set of inputs. Issuing that same fit again — after
a refactor, a rename, a code change that did not alter the numbers — produces a
second case file but not a second claim about the world.

**The first issue is the one that was committed to at that time.** That is what
makes it the claim: it was published before the outcome was known, and nothing
later can change when it was said.

**The direction of the error decides the rule.** Counting one fit twice
inflates `scores_counted` and computes coverage over a claim counted twice. If
that fit scored inside its band, coverage rises on a duplicate; if it scored
outside, the sample is padded. Either way the record reads better-founded than
it is, in the author's favour. That is the error that destroys a calibration
record, so the rule resolves against it.

---

## 4. What the record states

`archive/calibration.json` carries, alongside its counts:

| field | meaning |
|---|---|
| `cases_in_archive` | how many case files exist |
| `claims_counted` | how many unique fits those cases represent |
| `excluded_as_reissue` | how many cases were excluded under section 2 |
| `claims` | per counted claim: the fit, the case that counts, its issue date |
| `reissues` | per excluded case: which case supersedes it, and why |

A reader must be able to see the exclusion, not infer it from a number that is
smaller than the file count.

---

## 5. This rule does not change a score

Scores are written under `SCORING_RULE.md` and are final. This rule decides
which of them are counted, and nothing else. Excluding a case from the count
does not withdraw, amend or annotate its score.

---

## 6. Applicability

This version applies to the calibration record built on or after
**2026-09-09**, over all cases in the archive whatever their issue date.

The record is rebuilt in full from the cases and scores on disk every time. It
is never incremented, so applying this rule cannot require any stored value to
be revised.
