Rubric: volatile value correctness
Written by a person. Last read by a person on 2026-09-04, 4 days ago. Its facts were checked by the eval suite on 2026-09-07.
Enforced by check_volatile_schema, check_no_volatile_literals and
check_no_unrendered_templates.
The claim
No fact that changes when something upstream ships appears literally in prose, and every such fact carries a source and a date it was checked.
Observable evidence
- For each entry in
data/volatile.yaml: the presence ofvalue,sourceandverified. - For each line of prose: whether it contains a string equal to a value in the volatile layer.
- For a value shorter than four characters: additionally, whether the surrounding paragraph contains a word naming that value's concept.
- For each line of built HTML: whether it contains unrendered template syntax.
The pass bar
Every volatile entry has all three fields. No prose line contains a volatile value. No built page contains template syntax.
The bar is absolute rather than proportional because the failure is silent. A page with one stale model name looks exactly like a page with none, and the reader who acts on it has no way to tell.
Ambiguous cases
Short values need corroboration. A value of four characters or more is matched wherever it
appears: finding claude-opus-5 in a sentence means one thing. A shorter value is matched only
when the surrounding paragraph also contains a word naming its concept, because flagging every
occurrence of 2 would produce noise, and a check that cries wolf is one people learn to skip.
The corroborating words come from the key itself: retry.max_attempts yields retry, max and
attempt, so a hardcoded 5 in a paragraph about retry attempts is caught while 5 in a
paragraph about anything else is not.
Corroboration is scoped to the paragraph, not the line. Prose wraps, and a number is routinely on a different line from the noun that says what it is. A paragraph is about one thing, which makes it the honest unit.
The cost is that an unrelated digit will be flagged when it sits in a paragraph that discusses the concept. That false positive is the price of catching the wrapped case, and it is the right way round: a false positive is visible, and a missed stale value is not.
When the prose and the key use different words. Prose says "multiplying"; the key says
backoff_multiplier. No word is shared, so nothing corroborates and the value goes unchecked.
The entry may then declare its own terms:
backoff_multiplier:
value: 2
context: [multiplying, multiply, double]
An entry holding a short value that prose refers to by another name needs this, and the absence of it is a silent gap rather than a failure. That is the weakest point in this rubric.
Quoting a value on purpose. A page that documents this system has to be able to write a volatile value down, and so does a page explaining what changed in a release. Such a paragraph declares itself, with a reason:
<!-- volatile-ok: why this paragraph must quote a volatile value -->
The exemption covers one paragraph, never a file, and an exemption with no reason is itself a finding. Both of those are deliberate: a gate with no way out gets switched off wholesale the first time it is wrong, and a gate whose exemptions are invisible stops meaning anything. This rubric page carries three, which is the honest cost of documenting the check it describes.
Words that corroborate nothing. meta, site, value, default, name and config are
ignored as evidence: they appear in key paths without saying anything about what a value is.
Depluralisation is crude. Two rules: a trailing s is dropped, and ies becomes y, so
seconds matches second and retries matches retry. Anything beyond that wants a stemmer,
and a stemmer is a dependency and a source of surprises in a gate whose value is predictability.
A value that is also an ordinary word. A volatile entry whose value is a common English word will match prose that has nothing to do with it. The rule is that volatile values should be distinctive; where they cannot be, the check will produce a false positive and the entry needs a different shape rather than the check needing an exception.
Quoting the past deliberately. Prose that names a superseded value on purpose, for instance
to explain what changed, will fail this rubric. That is the correct outcome. Such a sentence
belongs in a version-diff view, which is filed as FR-2 and does not exist yet.
Values inside code blocks. Currently matched like any other prose. A code sample showing a literal is exactly as capable of going stale as a sentence, so this is deliberate.