metric_catalog — metrics.yaml catalog + spec-field accessors

Purpose

The config/catalog owner for the analysis pipeline: loads the metrics.yaml catalog and exposes
every spec-field accessor (units, labels, summary/log flags, the {variable: spec} index).
Strictly not math — the layer that turns a spec object into report-facing fields.

Role in the system

  • Split out of data_analyzer (Jun 18) so the math layer (data_analyzer Reductions/Deltas/SignalAnalysis)
    only ever reads fields off a spec object and never touches the YAML loaders.
  • Re-exported from data_analyzer for back-compat, so metric_alignment and lazy-load sites keep
    importing these names unchanged.
  • Catalog itself is loaded via pre_run_loader.MetricSpecLoader.load_metric_catalog().
  • metrics.yaml is the variable catalog (what is measured); judgment semantics (reduction, direction,
    gate) live in scoreboard.yaml instead — see orchestrator / the analysis pipeline contract.

Inputs / Outputs

  • In: a metric spec (Mapping, dataclass, Package, or RecursiveNamespace — all duck-typed),
    or a catalog, or a loader.
  • Out: scalar spec fields (units, labels, bool flags), the catalog specs tuple, and the cached
    {variable: spec} index.

Key functions

  • spec_field — read one field off a spec, duck-typed via object_fieldsanalysis/metric_catalog.py:24
  • spec_units / spec_group_label / spec_summary_label — display units + report labels — :39 / :44 / :52
  • spec_include_summary / spec_logged — bool flags with legacy-key fallbacks — :29 / :34
  • summary_group_for_spec — wrench/torque path routing for report grouping — :57
  • catalog_specs — specs as a tuple (dict / namespace / specs field) — :66
  • catalog_by_key — lazily build + cache the {variable: spec} index — :76
  • loaded_metric_catalog — load via a loader and attach the index — :86
  • metric_catalog_smoke — zero-arg smoke (python -m analysis.metric_catalog) — :93

Footguns

Hardcoded path-segment routing in summary_group_for_spec

The wrench/torque grouping is decided by literal "control_wrench" / "torque" checks against
spec.path, not by anything in metrics.yaml. Fragile if the path structure changes.
(analysis/INSIGHTS.md [config] + Open questions)

Legacy-key fallbacks are silent

spec_include_summary falls back to include, spec_logged to log_desired, spec_units to
unit — older catalog specs keep working, but a typo’d new key silently takes the fallback rather
than failing loud. (analysis/INSIGHTS.md [config])

catalog_by_key mutates the catalog

First call builds and caches catalog.by_key on the catalog object itself. One canonical builder
path keeps the index from being constructed inconsistently elsewhere. (analysis/INSIGHTS.md [config])

data_analyzer · metric_alignment · statistics · orchestrator · terminology