Practice · Measurement culture

Every Constant Is on Probation

Numbers in this codebase have a lifecycle: authored as provisional, exposed to observation, measured against samples, then pinned or replaced. This page covers the lifecycle and the boundary that makes it possible; the Explorer page covers the tooling, and the document-suite page covers the paper trail.

Constants are measured before they're believed

The recurring loop, visible on the materials, decoration and classification pages: author a provisional constant, mark it MVP-provisional with the precedent it follows, build the observability to sample real output, measure, then either pin the constant with a calibration test or replace it with a measured value and record the distribution table in the doc. The classification thresholds went through the full loop twice (the second pass caught the fixture skew). The scarcity weights kept their authored values but gained a test that pins the ratios between rungs, which is the honest version of "these numbers are right": nobody claims 0.25 is correct, only that scarce reading meaningfully rarer than available is now load-bearing and protected.

// the convention, condensed from materials.ts
// MVP-provisional (2GN.25 precedent): doc 05 names the drivers but supplies
// no numbers, so these are authored priors, expected to be retuned once
// generation is observable in the Explorer.
// Values pinned by materials.calibration.test.ts (2GN.84): what the pin
// makes load-bearing is the RATIO between rungs, not any absolute figure.
author provisionalmarked, with precedent make observablepanel or sampler measure1200–7200 artefacts pin or replacetest + doc table re-enters probation whenever upstream stages change the population
The lifecycle. The classification thresholds have been around it twice.
Procgen fails statistically Every individual artefact can look fine while the population is absurd: nine in ten objects "elite", a metal-free culture leading the world in wirework. Both happened. Unit tests assert properties of instances; the calibration suites here assert properties of distributions.

The engine boundary

Everything under engine/ is pure TypeScript: no Svelte, no browser, no ambient randomness, PRNG injected. The UI layer is a consumer. The same pipeline runs headless in tests, from CLI samplers and inside the browser workbench, with identical output; the boundary is enforced socially by module JSDoc and structurally by the import graph. The measurement culture depends on this: sampling 7200 artefacts is only cheap because the pipeline runs anywhere, and a sample is only meaningful because determinism makes it reproducible.

Where it lives Calibration suites: src/lib/data/*.calibration.test.ts, classification.test.ts · Boundary: src/lib/engine/ (module JSDoc) · Distribution tables: doc 12 §§2.24, 2.31, 2.33