Skip to main content

honestclock

CI

Point-in-time correctness for regulatory panel data. Separate what was knowable at a forecast date from what merely happened — and make the distinction a property of your types rather than a convention a reviewer has to check.

pip install honestclock

The problem

Records describing the same period arrive on different schedules.

In EPA's discharge-monitoring data, an effluent exceedance becomes visible a median of 20 days after the monitoring period, because the report that reveals it is the report that carries it. A missing report generates no row at all, and the non-compliance is not recorded for a median of 59 days.

Between those two dates, a facility whose compliance has already broken down still looks compliant to any filter written against the monitoring month.

The consequence is not a metric correction. It changes who is eligible: a pool that looks clean at the forecast date already contains failures. One dataset holds two prediction problems — detecting breakdowns already underway, and forecasting those still to come — and conflating them inflates what a precision number means.

What this package does

from honestclock import AsOfClock, PointInTimePanel, features as F

panel = PointInTimePanel(
    df,
    entity_keys=["permit_id", "parameter_code"],
    reference_col="month",          # the period the row describes
    availability_col="received_at", # when the row became knowable
)

clock = AsOfClock("2025-07", lookback=9, horizon=3)
visible = panel.visible_at(clock)          # cannot contain future data
labels  = panel.labels_at(clock, "exceedance")

X = F.assemble(
    visible,
    F.reporting_gap(visible),
    F.event_count(visible, "exceedance"),
    F.value_stats(visible, "ratio", clip_upper=5.0),
)

Three guarantees:

AsOfClock Derives a feature window and a label window from a forecast time and refuses to let them overlap.
VisibleFrame Cannot be constructed holding an observation that postdates its clock. The constructor validates and raises LookaheadError. Feature builders accept only this type.
audit_lookahead Tests a whole pipeline for dependence on unavailable data — catching leaks that never place a future row in a feature.

The audit is the part you probably need

A type can guarantee a frame holds no future rows. It cannot guarantee the pipeline is honest. An eligibility filter, a join against a "latest" snapshot, or a groupby computed before the cut can each admit information that did not exist at forecast time, without any future row ever appearing.

audit_lookahead answers the question empirically, without reading your code:

Does this function's output change when future rows are removed?

from honestclock import audit_lookahead

report = audit_lookahead(df, build_features, clocks, "received_at")
report.raise_for_status()   # AssertionError if the output depends on the future

It reports how many future rows were withheld at each forecast time, so a clean result cannot be mistaken for a strong one — an audit that withheld nothing proves nothing, and says so (report.vacuous).

A trap worth knowing about

event_share and event_count describe the same history and are not interchangeable as ranking signals. A share is bounded in [0, 1] and saturates: thousands of entities tie at 1.0, a top-k cut lands inside the tie group, and realised precision collapses toward the group's base rate.

In the study this package came from, a silence baseline built as a share scored 17.1% at a national top-100; the same history built as a count scored 45.2%. A 28-point difference that was an artefact of the data type, not the signal. Any comparison between a model and a one-column heuristic must build the heuristic as a count, or it is measuring representations.

Scope, honestly

This package is the point-in-time layer, not a model. It gives you a leak-resistant feature/label split and an auditor. It does not contain the Circuit Rider AI model, its trained weights, or any facility-level score, and it deliberately publishes no per-facility rankings.

The ECHO adapter is a schema contract and a panel builder (honestclock.echo), not a downloader. EPA's bulk files are large and their schema shifts between vintages; the contract is pinned in one module so a change surfaces as one failing test rather than as a quietly wrong number.

Domain-neutral core. Nothing outside honestclock.echo knows about EPA. Any panel with a reference time and an availability time works — drinking water, air permits, workplace safety, clinical registries, credit files.

Development

pip install -e ".[dev,parquet]"
pytest                                  # 153 tests, 100% branch coverage
ruff check src tests examples
ruff format --check src tests examples
mypy src/honestclock
python examples/quickstart.py

The suite includes property-based tests (via Hypothesis) asserting the availability invariant over thousands of generated panels, and adversarial tests in which deliberately leaky feature functions — modelled on real defects — must be caught by the auditor.

What is verified, and where

Because this package is about not making unsupported claims, here is the status of its own:

Claim Verified by
153 tests, 100% statement and branch coverage local + CI (--cov-fail-under=100)
Annotations are accurate (py.typed) mypy at default strictness, in CI
Works on the declared floor, pandas>=1.5 run against pandas 1.5.3 locally and in CI
Works on pandas 2.x pandas 2.3.3 locally, 2.0 and latest in CI
Installs and works as a built wheel clean-venv install, suite re-run against the artifact
The ECHO adapter parses real bulk data run against a real 4.5M-row FY2026 DMR extract: 1.67M pair-months, invariants held, median availability lag 16 days
requires-python >=3.9 3.9–3.13 all green in CI (9-job matrix)

mypy --strict is not clean: pandas' stubs return Any from most operations, and satisfying it would mean scattering casts that obscure the logic. Default strictness is the level this package claims.

Provenance

Extracted from the evaluation pipeline of Circuit Rider AI: Assistance-Oriented Compliance Triage for Small Wastewater Systems from Public Data. The 20-day/59-day latency figures, the share-versus-count artefact, and the two leak shapes the auditor models are findings from that work.

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

honestclock-0.1.0.tar.gz (38.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

honestclock-0.1.0-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file honestclock-0.1.0.tar.gz.

File metadata

  • Download URL: honestclock-0.1.0.tar.gz
  • Upload date:
  • Size: 38.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for honestclock-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d8ec1d6375944ecbac26d65dd513f31cb405f204ae4984a1a6ff96d6f50311ae
MD5 6562a5a7089b7012d547b032bc34ee9f
BLAKE2b-256 52d1a28f66ab3a21399e57547529d2fd71bdc717d7ad157ed2875a895ebb486c

See more details on using hashes here.

File details

Details for the file honestclock-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: honestclock-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for honestclock-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7feb6f0a6fb89860fb88e4accf1b158eb44e7a84ae842e91787742af0c0218b7
MD5 dc95b9d5f835e1c3c19f7c83fa9bf20b
BLAKE2b-256 dd5a7c74cfab76db5bcbe9e15fa0710964a11bfa8f83b2be3e420a4e551694ce

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page