API reference

Studies

Who decides whether a result confirmed the hypothesis, the author or the spec? In reward_lens.studies it is the spec, and it decides before the data exists. You write down the hypothesis, the predictions, and the kill criteria, freeze that into a content-hashed artifact, then run it. The run adjudicates the frozen predictions, not whatever the analysis wishes it had predicted. The discipline is studies and preregistration.

The spec

A StudySpec collects a Hypothesis, its Predictions, the KillCriterions that would sink it, and a SubjectQuery naming what to run it on. A prediction knows how to check a value against itself; a kill criterion knows when it has fired.

# class

StudySpec

Source

reward_lens.studies.spec.StudySpec

@dataclass(frozen=True)

The full specification of a confirmatory study (section 2.14).

Attributes

Name Type Default
id str
title str
science str
hypotheses tuple[Hypothesis, ...]
analysis str
subjects SubjectQuery field(default_factory=SubjectQuery)
kill_criteria tuple[KillCriterion, ...] ()
oracle_budget Cost | None None
version int 1
notes str ''
# class

Hypothesis

Source

reward_lens.studies.spec.Hypothesis

@dataclass(frozen=True)

A hypothesis with its registered prediction and the scoreboard row it addresses.

Attributes

Name Type Default
id str
statement str
prediction Prediction
scoreboard_row str | None None
# class

Prediction

Source

reward_lens.studies.spec.Prediction

@dataclass(frozen=True)

A registered, checkable prediction (R12).

metric names the quantity the analysis will compute; comparator and threshold state the predicted relationship (for example metric="spearman_chi_vs_drift", comparator=">", threshold=0.3). effect and ci_excludes optionally register a point effect size and a value the CI should exclude. This is what makes a claim uneditable after seeing the data: the prediction is hashed into the frozen study.

Attributes

Name Type Default
metric str
comparator Comparator
threshold float
effect float | None None
ci_excludes float | None None
rationale str ''

Methods

check(value: float) -> bool
src
# class

KillCriterion

Source

reward_lens.studies.spec.KillCriterion

@dataclass(frozen=True)

A schema-fielded kill criterion (R12, section 2.14).

If metric stands in comparator relation to threshold after the run, the criterion fires and the study produces a first-class negative-result report rather than a hidden failure. The description states, in one sentence, what a fired criterion means scientifically.

Attributes

Name Type Default
id str
metric str
comparator Comparator
threshold float
description str ''

Methods

fired(value: float) -> bool
src
# class

SubjectQuery

Source

reward_lens.studies.spec.SubjectQuery

@dataclass(frozen=True)

A declarative description of the study’s subjects (signals, organisms, datasets).

Held as ids/specs so the frozen study names exactly what it ran on. The runner resolves these to concrete objects at run time; the engine test injects them directly.

Attributes

Name Type Default
signals tuple[str, ...] ()
organisms tuple[str, ...] ()
datasets tuple[str, ...] ()
extra dict[str, Any] field(default_factory=dict)

Freeze and run

freeze stamps the spec with its content hash and the git sha into a FrozenStudy, giving it an identity of the form study:{id}@v{version}#{hash8}. run_study then executes it and adjudicates the frozen predictions, returning an outcome of confirmed, refuted, or inconclusive. Only a study that predated its data can reach the REGISTERED rung of trust. The worked version is freeze and run a study.

# func

freeze

Source

reward_lens.studies.freeze.freeze

freeze(
    spec: StudySpec,
    repo_dir: str | None = None,
    frozen_at: str | None = None
) -> FrozenStudy

Freeze a study spec, computing its StudyID and recording the git sha (gate 3).

The StudyID is study:{spec.id}@v{spec.version}#{hash8} where the hash is the first 8 hex characters of the spec’s content hash. Two specs that differ in any registered field (a prediction threshold, a kill criterion, the analysis path) get different ids, which is exactly the property that makes post-hoc editing visible as a new version.

# func

run_study

Source

reward_lens.studies.runner.run_study

run_study(
    spec_or_frozen: StudySpec | FrozenStudy,
    *,
    subjects: dict[str, Any] | None = None,
    store: EvidenceStore | None = None,
    analysis_fn: Callable[[StudyRun], StudyResult] | None = None
) -> tuple[FrozenStudy, StudyResult]

Run a study end to end: freeze if needed, execute the analysis, adjudicate against the spec.

The study must be frozen before it runs (a spec is frozen here if a raw spec was passed, so the freeze provably predates the evidence). The analysis function (resolved from the spec’s dotted path, or supplied directly for tests) computes the metrics its predictions named. The runner then checks each hypothesis’s prediction and each kill criterion against those metrics, sets the outcomes, and returns the StudyResult with its adjudicating evidence ids attached. Refutations and fired kill criteria are recorded as prominently as confirmations (I4).

The scoreboard

Scoreboard collects the standing claims, the theorems and the candidate laws, and their current status as registered evidence accrues for or against each one.

# class

Scoreboard

Source

reward_lens.studies.scoreboard.Scoreboard

Scoreboard(path: str | Path | None = None)

A persisted registry of theorem rows and their status (section 2.14).

Methods

save() -> None
src
register_row(row: ScoreboardRow) -> None
src
update_from_result(study_id: str, spec_hypotheses, result: StudyResult) -> None
src
Fold a study’s outcomes into the rows its hypotheses address.

A hypothesis maps to a scoreboard row via scoreboard_row. Confirmed and refuted outcomes update the row’s status; a row that receives both confirming and refuting evidence across hypotheses or studies becomes “mixed”. The adjudicating Evidence ids are recorded so the row can cite exactly what settled it.

render_markdown() -> str
src