Project

readout

0.0
There's a lot of open issues
Readout defines a Stat — a self-describing metric (key, title, plain-English definition, unit, timeframe, declared inputs) with a normalized result shape (value, shape, as_of, exact) and a Source adapter port. It depends on nothing concrete: any source (e.g. tally rollups) plugs in behind a Stat, so the display layer never couples to where a number comes from.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

Readout

A source-agnostic, self-describing metric contract.

A Readout::Stat describes a metric — its key, title, plain-English definition, unit, timeframe, and declared inputs — and exposes a normalized result shape (value, shape, as_of, exact). Behind every Stat is a Source (an adapter port); the Stat doesn't care where its number comes from.

That decoupling is the whole point: a display layer (e.g. dash_kit) renders Stats without knowing whether the number came from tally rollups, a live query, or a fixture. Swap the Source, keep the Stat.

Readout depends on nothing concrete — no Rails, no event source, no aggregation engine. Adapters bridge it to whatever produces the numbers.

Installation

gem "readout"

Status

The core contract works — a Stat reads through its Source and returns a normalized Result:

source = ->(inputs) { Readout::Result.new(value: 0.42, shape: :scalar, exact: true) }
stat   = Readout::Stat.new(
  key: :sales_conversion,
  title: "Sales Conversion",
  definition: "Share of qualified leads that became deals.",
  calculation: "deals ÷ qualified leads, within the period",
  unit: :percent,
  timeframe: "This month",
  source: source
)

stat.read(qualified: 100, won: 42).value   # => 0.42
stat.definition                            # the plain-English "what it captures"
stat.calculation                           # the "how it's computed"

A Stat is self-describing — title, definition, calculation, unit, timeframe — so a UI can explain any number without hardcoding meaning. Result carries value, shape, as_of, exact. Swap the Source (a tally-backed one, a live query, a fixture) without touching the Stat or the display.

Next: declared inputs (required/optional) + validation.

License

Available as open source under the terms of the MIT License.