Why publish this at all
Verification discipline is the least visible kind of quality. A careful codebase and a careless one look identical from the outside, and the difference only shows up years later, in whether anything you were told turned out to be true. So the discipline gets described rather than demonstrated, and a description of discipline is worth about as much as a promise.
The alternative is to publish the mechanisms and the numbers they currently produce, and then to wire the page itself into the build gate. Every figure below lives in one data module. A test in the content gate recomputes each one from the artifact it claims to describe, and fails if the page and the code disagree. That does not make the page interesting. It makes it checkable, which is the only property that matters for this kind of writing.
One instrument, frozen and fingerprinted
Everything a player or a Lab visitor sees resolved as a win, a loss, a difficulty band, or a margin comes from one judging instrument. That instrument is treated the way a calibrated measuring device is treated rather than the way application code is treated: it is not edited casually, and it carries a serial number.
The serial number is a digest. A build step reads the 10 modules that can move a verdict, hashes each one, and collapses those hashes into a single aggregate id. The current one is jlv-31e4f8fae539b1db. The manifest keeps the per-module digests too, so a drift report says which module moved rather than only that something did. Edit any of the 10 and the check fails until the id is deliberately regenerated by the one command that is allowed to do it, and every test that pins the id is updated in the same commit.
The perimeter is drawn wider than the judge directory on purpose. The verdict comes from an oracle that is injected into the judge, and that oracle rides in modules that live outside it: the composition engine, the run verifier, the explanation layer, the calibration constants. An earlier, narrower perimeter meant an edit to any of those four could move every verdict while the lineage id stood perfectly still. Widening it has a known cost, which the code records rather than hides: those files also carry display copy, so a prose-only edit now bumps the lineage and flags verdicts that did not actually change. That is the correct direction for a verdict perimeter. A spurious re-check is recoverable; silent drift under a fresh-looking id is not.
A second instrument, the aimed-effect certifier, carries its own id — currently clv-7251ed9a87ea4102 — and records inside its manifest the judge lineage it was cut against, so the pair cannot quietly fall out of step.
Two axes of freshness
Cached results are where verification quietly dies. A cache keyed on the wrong thing serves an answer that was true once, and nothing in the system notices. So each cached verdict is stamped with two independent fingerprints.
The first is a hash of that cell's judged inputs: the deployment model, the offered levers and their effects, budget, gates, pressures, timer, and the slice of catalogue the cell actually references. Presentation is deliberately outside that hash — narrative, win statements, teaching notes, difficulty display bands — because those cannot change an outcome. The practical consequence is the one that makes editing possible at all: a copy pass over the whole catalogue re-judges nothing.
The second axis is the instrument itself. The input hash cannot see a change to the judge, so the lineage id is stamped alongside it, and the serving predicate treats a lineage mismatch as stale whether or not any input moved. It fails closed. A retuned band or a shifted threshold drops every stamped verdict to “needs re-judging” rather than leaving a fleet of confident, obsolete answers in place.
The line to look for after a change is the batch runner's own summary. On the current tree it reads 150 cell(s), with the judged count at zero and the cache-hit count equal to it — every cached verdict proven fresh on both axes, nothing recomputed, and the claim available in one command to anyone who wants to run it.
Full-space enumeration, with the cap declared
Before a level ships, the judge does not search for a solution. It walks the entire legal configuration space for that level at each shipped difficulty setting, and evaluates each configuration through the same oracle live play uses. It counts the losing configurations as well as the winning ones, because the useful question is not whether a solution exists but how dense solutions are, how expensive the cheapest one is, and how many distinct approaches reach it. Only legality prunes the walk; nothing is pruned for being a bad idea.
Exhaustive enumeration needs a declared limit, and the limit is 1,500,000 configurations for a single cell. Above it the judge does not truncate. It switches to deterministic stratified sampling, walking the same canonical order at a fixed stride so the sample spreads evenly across the space, and it sets a flag on the report saying so. A sampled verdict is always legible as a sampled verdict.
Today that path is machinery for content that has not arrived yet. All 150 shipped cells are under the cap: 150 of 150 cached verdicts come from exact enumeration, and the largest legal space in the current catalogue is 7,807 configurations. The honest version of the claim is therefore stronger than the cap suggests, and narrower: nothing shipped is sampled, and the sampling code exists so that growth cannot quietly become approximation.
Audits that are themselves tested
The content gate runs 30 audits over the shipped data and copy. Repository-wide there are 36 audit scripts.
Two things about that number matter more than the number. First, the chain runs every member and reports all failures, rather than stopping at the first. That is not an aesthetic choice: the chain used to short-circuit, and a single red member near the front was found to be silently skipping everything behind it. Aggregating failures is how a gate stays a gate.
Second, an audit is not trusted because it passes. The house rule is that every audit ships with a test proving a clean baseline reports zero problems and that each synthetic violation fires exactly its own check and no other — so a check cannot rot into a no-op, and a real finding cannot be misattributed to the wrong rule. 26 of the 36 audit scripts carry that test under a matching name, which is the form the pairing is countable in.
The honesty machinery
These mechanisms do the work that a style guide cannot.
Names may not describe state
A node or a link is named for what it is or what it does, never for its status, strength, or behaviour — because changing exactly those is the entire point of the exercise. A latent second read is named for the check it is, not for its absence, and attached copy may narrate a deployment's documented history without asserting a fixed present state. 4 rule families are enforced over every shipped node and link name, with 5 reviewed exceptions, each carrying a written reason in the shared rule module rather than a silent suppression. Attached copy is screened separately and more narrowly, by a short list of present-state phrases rather than by those rule families, which is what lets it narrate history at all.
The two channels cannot touch
The cited-evidence side and the fictional side are separated mechanically, in both directions. Game content cannot import the Lab's cited scenario data. Real deployment names live on the Lab and audit side, and the registry of them screens the write path that authored game content goes through, rather than being re-checked over shipped content on every run. The evidence registry is generated-only and untouched by game work. Exactly two interruptive interface classes are sanctioned, enumerated, and enforced as exactly two. The import ban and the interruptive-class count are asserted statically on every run; the name registry is a write-path screen, and the distinction is worth stating because only the first two would catch a violation that somehow reached the repository.
Deviations are written down
The campaign is fiction on an empirical base, so it sometimes needs to relax a register the Lab holds to. Those relaxations go into a dated, append-only ledger for owner review instead of being absorbed silently: 90entries so far. What the ledger explicitly cannot authorize is the part that would matter — it cannot relax the evidence registry, the ban on naming real systems in game theming, the ban on model identifiers, or the Lab channel's cited posture. A ledger that could excuse anything would be decoration.
The two engines are checked against each other
The Lab is authored arithmetic; the research program underneath it is a dynamical model. The only property both are supposed to share is the direction a governance move pushes. That used to ride on prose rationale beside the constants. It is now an audit: 9 mapped lever families across 121 deployment models that resolve to a research-side record, 1,089 comparisons in all. 979 agree. 0 are sign contradictions, and that is a hard gate with no allowlist mechanism at all — the data model has nowhere to put one. The remaining 110 are presence divergences, where one engine reads a move as inert and the other reads a direction. They are not papered over: each is enumerated with its live numbers and recorded in a baseline with a written reason, the audit fails on a new one or on one that has changed sides, and the baseline drains as the two catalogues converge.
The comparison is of sign only, never magnitude, and the reason is a boundary rather than a shortcut. One side is a bounded authored gauge over small integer intensities; the other is a steady-state quantity from a differential system. Neither is a calibration of the other, and an audit that compared magnitudes would be inventing agreement it had no standing to find.
Escalate with numbers
The rule that does the most work is a cultural one with a mechanical edge: content adjusts to the instrument, never the instrument to content. When a level turns out to be jointly infeasible under the invariants, the required response is to escalate with the numbers, not to loosen the gate that caught it. A threshold that moves to make a red test green is how a measurement stops being a measurement.
When the instrument does have to move, the ceremony leaves a record, and the record is deliberately unflattering. The comment above the pinned lineage assertion reads like a flight log: each bump, what changed, and the measured result — cells re-judged, reports byte-identical, winnability outcomes flipped. It includes an entry recording a procedural breach in plain language, where two parallel commits edited perimeter modules without the ceremony, so the recorded id no longer described the bytes on disk. The repair regenerated the manifest over the current bytes and proved, by a forced full re-judge into a scratch directory, that no verdict had moved: nothing re-judged, no report body different, no winnability flip. Procedural breach, zero measured drift, both facts written down.
That is the habit the rest of this page rests on. Measured deltas get recorded even when they are embarrassing, because a repository that hides its small failures cannot be believed about its large successes.
Check these numbers
Every figure above appears in the table below, and every row is recomputed from the named artifact by a test that runs in the content gate. The values move when the repository moves — that is the intent. What cannot happen is for the page to keep saying something the code has stopped doing.
| Figure | Value | Checked against |
|---|---|---|
| Current judge lineage id | jlv-31e4f8fae539b1db | the judge lineage manifest |
| Modules inside the lineage digest | 10 | the judge lineage manifest |
| Current certifier lineage id | clv-7251ed9a87ea4102 | the certifier manifest |
| Cached machine verdicts | 150 | the solver-report cache |
| Verdicts from exact enumeration, not sampling | 150 | the solver-report cache |
| Enumeration cap before sampling, per cell | 1,500,000 | the density judge |
| Largest legal configuration space in the catalogue | 7,807 | the solver-report cache |
| Audits inside the content gate | 30 | the test-chain manifest |
| Audit scripts in the repository | 36 | the scripts directory |
| Audits carrying a teeth test under a matching name | 26 | the scripts directory and the test directory |
| Name-neutrality rule families | 4 | the name-neutrality module |
| Reviewed name exceptions, each with a written reason | 5 | the name-neutrality module |
| Deployment models that resolve to a research-side record | 121 | the direction-parity inputs |
| Mapped lever families compared across both engines | 9 | the direction-parity inputs |
| Direction comparisons run | 1,089 | the direction-parity audit |
| Comparisons where both engines agree | 979 | the direction-parity audit |
| Sign contradictions between the two engines | 0 | the direction-parity audit |
| Presence divergences recorded with written reasons | 110 | the direction-parity audit |
| Dated entries in the fiction-channel deviation ledger | 90 | the deviation ledger |