API reference

Measure and indices

What turns a signal into a measurement you can file? One runner. reward_lens.measure holds the observable protocol, the eleven white-box instruments of the battery, and the eighteen scalar indices, and every one of them returns Evidence through the same gate-enforcing runner. The narrated tour is under instruments.

The runner

An Observable declares the capability it needs and the gauge status of what it returns. run enforces the capability and the frame requirement before the observable is allowed to touch a signal, and threads the calibration and study facts through so the resulting evidence comes out with its trust level already computed. A Context carries the signal, the data view, and any comparison target.

# func

run

Source

reward_lens.measure.base.run

run(observable: Observable, ctx: Context) -> Evidence

Run an Observable under the gates (section 2.8.1).

Enforces R3 (the signal must declare the required capability) and gate 2 (a covariant cross-signal comparison requires a frame) before delegating to measure. Gates 1 and 3 are applied inside ctx.emit. The result is a fully gated Evidence; there is no path that returns an ungated number.

# class

Context

Source

reward_lens.measure.base.Context

@dataclass

Everything an Observable needs to run, plus the machinery to emit gated Evidence.

signal is the primary subject; others names additional signals for cross-signal comparisons (an effective-angle Observable puts the second model here). view is the DataView; readout selects which readout to read; frame supplies the gauge frame for covariant/invariant observables; study is the frozen StudyID when the run is registered (gate 3). regime describes the data regime for the calibration lookup (gate 1).

Observables call emit to build their Evidence; emit applies gates 1 and 3 centrally so an Observable cannot forget them. The runner (run) applies the capability check and gate 2.

Attributes

Name Type Default
signal RewardSignal
view Any None
readout str 'reward'
others tuple['RewardSignal', ...] ()
frame FrameID | None None
study str | None None
is_comparison bool False
regime dict[str, Any] field(default_factory=dict)
stats dict[str, Any] field(default_factory=dict)

Methods

subject(extra: dict | None = None) -> SubjectRef
src
Build the SubjectRef naming the signals, dataset, readout, frame, and interventions.
emit(
    value: Any,
    *,
    uncertainty: Uncertainty | None = None,
    gauge: GaugeStatus | None = None,
    parents: tuple[EvidenceID, ...] = (),
    cost: Cost | None = None,
    subject_extra: dict | None = None
) -> Evidence
src
Build a gated Evidence for the current Observable’s result.

Applies gate 1 (looks up a calibration reference for this observable and subject; absent means EXPLORATORY) and gate 3 (a frozen study makes it REGISTERED). Gate 2’s gauge status is taken from the Observable’s declaration unless overridden. The trust level falls out of make_evidence, never set here directly.

# class

Observable

Source

reward_lens.measure.base.Observable

@runtime_checkable

Bases: Protocol

A measurement (section 2.8.1).

requires is the capability the signal must declare; gauge_status is how the value transforms under the gauge group; faithful_to names the Appendix A theory object it instantiates (or None), and deviations lists explicit departures from it. measure computes the Evidence, calling ctx.emit to build it so gates 1 and 3 are applied centrally.

Attributes

Name Type Default
name str
version str
requires Capability
gauge_status GaugeStatus
faithful_to str | None
deviations tuple[str, ...]

Methods

measure(ctx: Context) -> Evidence
src

The battery

Eleven observables, imported from reward_lens.measure.battery. The first few read the reward geometry directly off activations and the linear readout, and are gauge-invariant. The last few compare readouts or SAE features and are RAW_ONLY or need a frame, so they refuse a cross-model claim without one.

LensCrystallization finds the depth where the chosen-versus-rejected margin reaches half its final value: the layer the model made up its mind. See reward lens and crystallization.

# class

LensCrystallization

Source

reward_lens.measure.battery.lens.LensCrystallization

Bases: BaseObservable

Layer-by-layer preference formation and its crystallization depth (E02).

Requires activation capture and a linear readout. The crystallization fraction is a depth in [~0, 1] and is gauge-invariant (comparable across signals), which is why E02 headlines the per-model mean fraction directly.

Methods

measure(ctx: Context) -> Evidence
src

DirectLinearAttribution splits the reward differential into a signed share per component. It reads where the reward is visible, which is not the same as what causes it; that gap is the subject of observational versus causal.

# class

DirectLinearAttribution

Source

reward_lens.measure.battery.dla.DirectLinearAttribution

Bases: BaseObservable

Signed per-component reward attribution for preference pairs (E03/E04).

Requires activation capture and a linear readout. The contributions are in reward units and sum to the reward differential; the invariant scientific summary is their ranking, which E04 compares to the patching ranking. Marked INVARIANT because the reward is gauge-fixed by the head and the faithfulness statistic is rank based.

Methods

measure(ctx: Context) -> Evidence
src

PatchGrid is the causal counterpart: the effect on the reward of patching a component or head. PathEffect measures a two-hop sender-to-receiver path. Both are gated to a real model at head granularity.

# class

PatchGrid

Source

reward_lens.measure.battery.patch.PatchGrid

Bases: BaseObservable

PatchGrid(granularity: str = 'component') -> None

Causal patch effects for every component (or head) on preference pairs (E15).

granularity is "component" (attention and MLP sublayers, the default) or "head" (every attention head). Requires activation capture and a linear readout. Patch effects are in reward units and are gauge-invariant within a signal.

Methods

measure(ctx: Context) -> Evidence
src
# class

PathEffect

Source

reward_lens.measure.battery.path.PathEffect

Bases: BaseObservable

Two-hop head-to-receiver path effect on reward for preference pairs (E15).

Requires activation capture and a linear readout. The path effect is in reward units and gauge-invariant within a signal.

Methods

measure(ctx: Context) -> Evidence
src

ConceptDoseResponse measures a concept direction’s reward alignment and its causal dose-response slope: push the activation along the concept, watch the reward move.

# class

ConceptDoseResponse

Source

reward_lens.measure.battery.concept.ConceptDoseResponse

Bases: BaseObservable

Concept direction, its reward alignment, and its causal dose response (E08).

Requires activation capture and a linear readout. The concept is read from the pairs in the view (chosen positive, rejected negative). Marked RAW_ONLY because the direction, its alignment, and the dose are all in raw residual-stream coordinates.

Methods

measure(ctx: Context) -> Evidence
src

BiasBattery reports a standardized reward bias per axis with a lineage-honest sample size, and PromptSNR the power signal-to-noise of the reward delta.

# class

BiasBattery

Source

reward_lens.measure.battery.bias.BiasBattery

Bases: BaseObservable

Per-axis standardized reward bias with lineage-honest effective sample size (E06).

Requires only scores. The view is grouped by each pair’s axis; each axis reports its reward delta effect size and the honest ESS of its seeds. INVARIANT (Cohen’s d is standardized).

Methods

measure(ctx: Context) -> Evidence
src
# class

PromptSNR

Source

reward_lens.measure.battery.snr.PromptSNR

Bases: BaseObservable

Per-axis reward signal-to-noise ratio (E16).

Requires only scores. The view is grouped by each pair’s axis. INVARIANT (a dimensionless power ratio).

Methods

measure(ctx: Context) -> Evidence
src

ConflictMatrix reads the cosine geometry between per-axis reward terms, and CircuitJaccard the top-component overlap between two models.

# class

ConflictMatrix

Source

reward_lens.measure.battery.conflict.ConflictMatrix

Bases: BaseObservable

Inter-axis reward-term conflict geometry (E09).

Requires activation capture and a linear readout. The view must span at least two axes. Marked RAW_ONLY because the term cosines are in raw residual-stream coordinates.

Methods

measure(ctx: Context) -> Evidence
src
# class

CircuitJaccard

Source

reward_lens.measure.battery.circuit.CircuitJaccard

Bases: BaseObservable

Top-component circuit overlap between two reward models (E05).

ctx.others[0] is the second signal to compare against ctx.signal; both are attributed on the same view. top_k (from ctx.regime['top_k'], default 5) sets the circuit size. Requires activation capture and a linear readout. INVARIANT: the overlap is a set membership over named components, not a covariant geometric quantity.

Methods

measure(ctx: Context) -> Evidence
src

FeatureRewardAlignment asks which SAE features drive the reward, and MultiObjectiveGeometry reads the per-objective readout geometry of a multi-objective head like ArmoRM.

# class

FeatureRewardAlignment

Source

reward_lens.measure.battery.feature.FeatureRewardAlignment

Bases: BaseObservable

Per-feature reward alignment of an SAE over a signal (E12).

The SAE comes from ctx.regime['sae'] (a TopKSAE whose d_model matches the signal). When absent, a small random SAE is built so the mechanics run and the result is flagged untrained. Requires a linear readout. RAW_ONLY: alignments depend on the SAE and residual bases.

Methods

measure(ctx: Context) -> Evidence
src
# class

MultiObjectiveGeometry

Source

reward_lens.measure.battery.geometry.MultiObjectiveGeometry

Bases: BaseObservable

The cosine geometry of a multi-objective reward head (E18).

Requires a linear readout with more than one objective row. Marked RAW_ONLY because the cosines are in raw residual-stream coordinates; they are a single-model internal geometry and are not cross-model comparable without a frame.

Methods

measure(ctx: Context) -> Evidence
src

The index library

Eighteen scalar diagnostics, imported from reward_lens.measure.indices. Each pairs a definition with a pure-numpy function and returns Evidence. All of them default to EXPLORATORY: there is no calibration provider wired for the index library yet, so they name a quantity honestly without claiming a validated regime. Sixteen are gauge-invariant; VCE and Contested are covariant and need a frame to compare. The narrated version is the index library.

# class

KUI

Source

reward_lens.measure.indices.kui.KUI

Bases: BaseObservable

KUI(
    properties: Sequence[Property] | None = None,
    *,
    null_draws: int = 10000,
    seed: int = 0
) -> None

A1 Knowledge-Utilization Index: the (decode, mediate) plane and the diagonal distance.

Requires activations and a linear readout on the production path (a probe reads decodability from h and a direction gives the mediation proxy). The battery of properties is injected (each a Property with a decodability and either a measured Δr or a direction w_P); the concept layer supplies probes and directions in production. When the mediation proxy is used, the cosine is read against a random-direction null so a “represented-but-unpriced” flag beats the high-dimensional cosine noise floor. Gauge is INVARIANT: the plane is a within-battery, within-signal object.

Methods

measure(ctx: Context) -> Evidence
src
# class

Distortion

Source

reward_lens.measure.indices.distortion.Distortion

Bases: BaseObservable

Distortion(
    directions: np.ndarray | None = None,
    *,
    coverage: Sequence[float] | None = None,
    curvature: Sequence[float] | None = None,
    names: Sequence[str] | None = None
) -> None

A2 per-dimension distortion v2, with KUI supplying the coverage term.

Requires activations and a linear readout. Takes a battery of property directions and their KUI mediation-percentile coverage (injected; the concept layer and the KUI index supply both in production), computes the linear sensitivity |w_r · v_P| (or uses an injected Hessian curvature), and reports the per-dimension distortion. Gauge is INVARIANT: distortion is a within-signal per-direction magnitude.

Methods

measure(ctx: Context) -> Evidence
src
# class

CoverageDisparity

Source

reward_lens.measure.indices.coverage_disparity.CoverageDisparity

Bases: BaseObservable

CoverageDisparity(coverage: Sequence[float] | None = None) -> None

v1’s coverage statistic, kept reproducible under its honest name (not Wang-Huang distortion).

Takes a battery of per-property coverage values (injected; the concept/KUI layer supplies them in production) and reports their disparity. faithful_to is None on purpose: this instantiates no Appendix A theory object, it preserves a v1 statistic, and the deviation note says so. Gauge is INVARIANT.

Methods

measure(ctx: Context) -> Evidence
src
# class

TeacherCompatibility

Source

reward_lens.measure.indices.teacher_compatibility.TeacherCompatibility

Bases: BaseObservable

A3 induced reward variance w_rᵀ Σ_π w_r, layer- and spectrum-decomposable.

Requires activation capture and a linear readout. Reads w_r off the readout, captures the on-policy final-token activations at the readout site (and at every residual layer when the signal reports its depth, for the layer decomposition), and reports the total with its spectral split. Gauge is INVARIANT: it is a single-signal functional, not a cross-signal comparison. It carries reward-scale² units, so a cross-model magnitude comparison first needs the two rewards on a common scale; that caveat is stated as a deviation rather than silently ignored.

Methods

measure(ctx: Context) -> Evidence
src
# class

TailIndex

Source

reward_lens.measure.indices.tail.TailIndex

Bases: BaseObservable

TailIndex(
    feature_bank: FeatureBank | None = None,
    *,
    quantile: float = 0.9,
    bootstrap: int = 500,
    ci: float = 0.95,
    seed: int = 0
) -> None

A4 right-tail exponent of the reward, aggregate and per-feature.

Requires scores (and activations plus a linear readout for the per-feature tails). Scores the base policy samples, estimates the aggregate tail with a bootstrap CI on the shape, and, when a feature bank is available, estimates each feature’s tail as the proxy for its contribution to r. Gauge is INVARIANT: the tail regime and the dimensionless shape are scale-free properties of one signal, though τ and λ_c carry reward-scale units, which is noted as a deviation.

Methods

measure(ctx: Context) -> Evidence
src
# class

VerificationScore

Source

reward_lens.measure.indices.verification_score.VerificationScore

Bases: BaseObservable

VerificationScore(
    dr_total: float | None = None,
    dr_error_span: float | None = None
) -> None

A6 causal fraction of the correctness reward gap that lives at the labeled error span.

Requires prefix scores (the process/verifier reward) on the production path, plus the interventions subsystem for the clean-twin span patch. Here the measured deltas are injected (dr_total, dr_error_span) so the attribution arithmetic is exercised without waiting for interventions; the production path substitutes the patched deltas. Gauge is INVARIANT: VS is a fraction.

Methods

measure(ctx: Context) -> Evidence
src
# class

StyleShare

Source

reward_lens.measure.indices.style_share.StyleShare

Bases: BaseObservable

StyleShare(
    delta_h: np.ndarray | None = None,
    style_basis: np.ndarray | None = None
) -> None

A6 fraction of the correctness reward gap the reward reads off style directions.

Requires activations and a linear readout on the production path (Δh from clean/corrupted twins, the style subspace from the concept layer’s style dictionary). Here Δh and the style basis are injected so the projection arithmetic is exercised directly. Gauge is INVARIANT: the style share is a reward fraction.

Methods

measure(ctx: Context) -> Evidence
src
# class

ReceiptReliance

Source

reward_lens.measure.indices.receipt_reliance.ReceiptReliance

Bases: BaseObservable

ReceiptReliance(dr_receipt: float | None = None, dr_total: float | None = None) -> None

A7 fraction of the corruption reward effect the reward reads off receipt spans.

Requires span-typed inputs and prefix scores on the production path (the receipt-span patch and the falsify-receipt/falsify-narrative arms). Here the arm deltas are injected so the attribution arithmetic runs directly. Gauge is INVARIANT: RRS is a fraction.

Methods

measure(ctx: Context) -> Evidence
src
# class

Skepticism

Source

reward_lens.measure.indices.skepticism.Skepticism

Bases: BaseObservable

Skepticism(
    r_receipt_absent: np.ndarray | None = None,
    r_receipt_failure: np.ndarray | None = None
) -> None

A8 whether the reward treats a missing receipt as failure (skeptical) or reward (credulous).

Requires span-typed inputs on the production path (the receipt-absent and receipt-failure conditions of matched narratives). Here the two score vectors are injected so the difference is exercised directly. Gauge is INVARIANT with respect to representation, though S carries reward-scale units, noted as a deviation.

Methods

measure(ctx: Context) -> Evidence
src
# class

Coherence

Source

reward_lens.measure.indices.coherence.Coherence

Bases: BaseObservable

Coherence(
    directions: np.ndarray | None = None,
    *,
    spectrum: Any = None,
    null_draws: int = 5000,
    seed: int = 0
) -> None

A9 cross-criterion coherence, contamination, Welch floor, and d_eff.

Requires a multi-readout signal (a reward exposing several criterion directions). The criterion directions are taken from the signal’s criterion:k readouts (ArmoRM’s objectives are first-class, never a row mean), or injected directly for the synthetic test. Reports the coherence matrix, the Welch bound and whether the criteria are over-packed past d_eff, and the mean contamination, with the mean coherence read against a random-direction null so “the criteria are more aligned than chance” beats the high-dimensional noise floor. Gauge is INVARIANT: the Gram of one signal’s own criteria is invariant under a shared orthogonal transform of the representation; a cross-signal criterion comparison would be COVARIANT and frame-gated, which is noted as a deviation.

Methods

measure(ctx: Context) -> Evidence
src
# class

DarkReward

Source

reward_lens.measure.indices.dark_reward.DarkReward

Bases: BaseObservable

DarkReward(named_contributions: np.ndarray | None = None) -> None

A10 fraction of reward variance mediated by no named channel.

Requires scores. The named-channel contributions are injected (the concept/criterion layer supplies them in production; the causal reading uses steering-measured contributions). Reports the dark fraction. Gauge is INVARIANT: a variance fraction is scale-free.

Methods

measure(ctx: Context) -> Evidence
src
# class

InterpCoverage

Source

reward_lens.measure.indices.interp_coverage.InterpCoverage

Bases: BaseObservable

InterpCoverage(
    feature_contributions: np.ndarray | None = None,
    error_contributions: np.ndarray | None = None
) -> None

A11 fraction of reward routed through interpretable features rather than error nodes.

Requires activations on the production path (the attribution graph is built from them). The feature and error-node contributions are injected here; the production path supplies them from an attribution graph with a scalar reward sink. Gauge is INVARIANT: a coverage fraction is scale-free.

Methods

measure(ctx: Context) -> Evidence
src
# class

Chi

Source

reward_lens.measure.indices.chi.Chi

Bases: BaseObservable

Chi(
    feature_bank: FeatureBank | None = None,
    *,
    gold: Any = None,
    null_draws: int = 2000,
    seed: int = 0
) -> None

A12 susceptibility spectrum χ_i = Cov_0(f_i, r) over a feature bank on base-policy samples.

Requires activation capture, scores, and a linear readout. Captures the base-policy activations, turns them into feature values through the feature bank (injected, else the concept layer’s default, else a graceful no-bank report), scores the same samples, and reports the χ spectrum with a per-feature shuffle null. When a gold signal is supplied it also scores the gold objective and flags the predicted hack modes (χ_i > 0 with χ_gold_i ≤ 0).

Gauge is INVARIANT: χ is a within-signal spectrum relative to a fixed feature bank. Comparing individual χ_i across signals requires the same bank read in a shared frame; that is a cross-signal comparison the caller must set up, and is noted as a deviation.

Methods

measure(ctx: Context) -> Evidence
src
# class

VCE

Source

reward_lens.measure.indices.vce.VCE

Bases: BaseObservable

VCE(
    reward_alignment: float | None = None,
    capability_alignment: float | None = None,
    *,
    d: int | None = None,
    k: int | None = None,
    null_draws: int = 1000,
    seed: int = 0
) -> None

A14 Value Convergence Excess: reward-subspace agreement beyond capability agreement.

A cross-signal comparison: COVARIANT and frame-gated (the reward and capability alignments must be computed on frame-canonicalized subspaces of the RM pair). The two same-metric alignment scalars are injected here (with the ambient d and subspace k for the null); the production path computes them through geometry.subspace in a shared frame. Reports VCE against the RUM-identifiability null.

Methods

measure(ctx: Context) -> Evidence
src
# class

Legibility

Source

reward_lens.measure.indices.legibility.Legibility

Bases: BaseObservable

Legibility(
    predicates: np.ndarray | None = None,
    costs: Sequence[float] | None = None,
    *,
    budgets: Sequence[float] | None = None
) -> None

A15 legibility frontier fidelity(K), its knee K*, and the tacit residual.

Requires scores. The predicate library and description-length costs are injected (the concept layer’s difference dictionary supplies them in production). Reports the fidelity curve over the budget, the knee, and the illegible tacit residual. Gauge is INVARIANT: fidelity is a rank agreement, and the tacit residual’s variance fraction is scale-free.

Methods

measure(ctx: Context) -> Evidence
src
# class

EvalAwareness

Source

reward_lens.measure.indices.eval_awareness.EvalAwareness

Bases: BaseObservable

EvalAwareness(
    is_benchmark: np.ndarray | None = None,
    *,
    steering_delta_r: float | None = None,
    null_draws: int = 2000,
    seed: int = 0
) -> None

A17 balanced accuracy of a benchmark-vs-organic probe on reward activations, with a null.

Requires activations. Labels marking which inputs are benchmark-style are injected (the data plane supplies them in production); the causal Δr from steering the recognition direction is injected and is the production path. Reports the held-out balanced accuracy against a label-permutation null. Gauge is INVARIANT: balanced accuracy is a within-signal classification quality.

Methods

measure(ctx: Context) -> Evidence
src
# class

RobustnessSNR

Source

reward_lens.measure.indices.snr.RobustnessSNR

Bases: BaseObservable

RobustnessSNR(groups: Any = None) -> None

Robustness SNR: between-condition reward signal over within-condition paraphrase noise.

Requires scores. The paraphrase-cluster labels are injected (or read from the view’s group ids); the production path scores paraphrase clusters through the signal. Gauge is INVARIANT: a variance ratio is scale-free.

Methods

measure(ctx: Context) -> Evidence
src
# class

Contested

Source

reward_lens.measure.indices.contested.Contested

Bases: BaseObservable

Contested(
    delta_h: np.ndarray | None = None,
    disagreement: np.ndarray | None = None
) -> None

Contested direction: the representation axis annotators disagree along.

Requires activations. The per-pair Δh and the disagreement signal are injected (the data plane’s annotator records supply disagreement in production). The direction is COVARIANT: comparing contested directions across signals requires a shared frame (gate 2). Within one signal the recovered axis and its correlation are reported directly.

Methods

measure(ctx: Context) -> Evidence
src