metrics — the metric CATALOG (what is measured)

Purpose

The schema anchor-tree that defines, for every logged signal, what is measured: its variable
name, delta method (how a raw signal becomes an error), unit, group label, reductions, and
include flags. It is the what, not the judgment — the pass/fail gates live in
scoreboard. Single source of truth for what the pipeline catalogs and how it reduces each signal.

Structure

The file is one big YAML inheritance tree: a default_global anchor (&metric-default) seeds defaults
that nested anchors and leaf specs override via <<: merge. Top-level sections:

  • default_global — root defaults (continuous, log_desired, reductions, unit, find_norm, cc_frame, a delta sub-block, include).
  • state — raw plant state (coordx); find_norm: false.
  • tracking_error — the error signals: com (p_c/v_c), base (z_b/omega_b), arm (p_e/z_e/nu_e). Anchors split position / lin_vel / pointing / ang_vel defaults.
  • control_effort — actuator forces/torques/wrenches, each in a coordinated-control (cc_frame: true) and actuator (cc_frame: false) form.
  • guidance — reference-side signals: com progress/alpha, targeting mode + step-event counters + scorer score terms + tgt_x.
  • inspection — coverage outcomes: area_coverage_frac, unique_triangles (reduced at final).
  • diagnostics — guidance offsets/raw refs, controller demand, and conditioning (derate_fraction/s_min_J, gamma_scale, kappa_J, v_sat).

Key knobs/sections

Load-bearing fields (point at the YAML for the exhaustive leaf list):

key pathwhat it controlsdefault / examplenote
default_global (&metric-default)root defaults every leaf inherits via <<:include: true, find_norm: true, reductions: nullYAML merge keys (<<:) build the whole tree; edit anchors, not leaves, to move a default
<leaf>.variablethe logged signal key the spec binds top_e, z_b, s_min_Ja leaf missing variable: raises loudly in the loader (reject_missing_variable)
<leaf>.reductionsscalar reductions cataloged for the signal[max, rms, final, p95, p99]drawn from the Reductions enum in data_analyzer; most reduce |x| (see footgun)
<leaf>.delta.methodhow a raw signal becomes a per-step errorstep, angle_step, jump, changestep=finite diff; angle_step=angle-aware step for pointing; jump=raw jump; change=discrete-mode change count
error.pointing (&z-default)routes error through the versine 1 − cos θtrue for z_b/z_eNOT the chord, NOT angle_between — see measurement contract
<leaf>.includewhether the metric is cataloged on by defaultanchors set false; arm p_e/z_e/nu_e override truedefault_pointing is include: false at the anchor; arm/base pointing re-enable selectively
<leaf>.unitdisplay/units stringm, m/s, Nm, normalized, nullunitless metrics must read "" not NaN downstream (pivot-drop footgun)
cc_framecoordinated-control vs actuator frame of a wrenchtrue (f_c, tau_b_oplus) / false (f_b, tau_b)distinguishes the circumcentroidal reduced wrench from the actuator command (breve_controller)
derate_fraction.thresholdfrac_below floor on s_min_J for the throttle-share metric0.025mirrors controller.arm.null_space.freeze_floor — keep in sync when the controller floor is tuned

Who reads it

  • pre_run_loaderMetricSpecLoader.walk_metric_specs walks the tree, inheriting parent context; default_global seeds the defaults each leaf overrides.
  • metric_catalog — spec accessors + catalog_by_key (lazy {variable: spec} index) over the loaded catalog.
  • data_analyzerSignalAnalysis/DataSummary read fields off a spec object (the Reductions/Deltas enums it drives by string).
  • logger — completeness is checked against scoreboard, not this full catalog (catalog metrics are config-conditional).
  • parameter_loader — loads the raw YAML to a RecursiveNamespace; dot-access, never raw-YAML reasoning.

Footguns

metrics.yaml ≠ scoreboard.yaml — separate concerns

This file is the variable catalog (what is measured). scoreboard is the judgment layer
(how it is judged: reduction, direction, gate, weight, after: startup window). MetricSpecLoader
and ScoreboardSpecLoader are their respective parsers — do not put a gate here.
(analysis/INSIGHTS.md pre_run_loader [config])

One-in-one-out edit policy; no hardcoded strings

User-maintained to prevent cruft. Standing policy: retire at least one old metric for every new
addition
. No hardcoded strings belong here. (YAMLs_by_domain/INSIGHTS.md metrics.yaml [config])

v_sat / v_max is NOT a catalog threshold

v_sat (velocity-saturation flag) is derived per-step via data_analyzer.saturation_series, NOT
stored at catalog level. The matching v_max threshold lives on the run-spec sweep entry, not
here — adding it to the schema is a footgun. (YAMLs_by_domain/INSIGHTS.md metrics.yaml [io])

derate_fraction.threshold must track the controller floor

Its 0.025 mirrors controller.arm.null_space.freeze_floor (the speed-throttle floor). The two
values must stay in sync when the controller floor is tuned. (YAMLs_by_domain/INSIGHTS.md metrics.yaml [config])

Pointing is the versine; reductions abs-map

pointing: true routes through the versine 1 − cos θ, not the raw vector difference. Separately,
every reduction EXCEPT the is_signed members reduces \|x\| — so MAX = max\|x\| but MIN is a
signed minimum. (YAMLs_by_domain/INSIGHTS.md metrics.yaml [config]; data_analyzer magnitude footgun)

scoreboard · pre_run_loader · metric_catalog · data_analyzer · logger · parameter_loader · breve_controller · robot · current_sota · terminology