Engineering health
Status: 🚧 Planned. Tooling, reproducibility, and rigour improvements that do not change forecast behaviour. One section is outstanding — the scientific-rigor tests, #229, in the v0.3 epic #6 — and this page is deleted when that section ships. Task ordering lives in the GitHub Project board.
Scientific-rigor tests and cleanup
Issue: #229
Runs after the live service and monitoring land. The feature-level no-lookahead tests, cross-mode equivalence test, idempotency tests, and the full-stack cross-process MLflow test all exist. Four "not cheating" guardrail tests from the original testing strategy remain unwritten, plus general cleanup.
Implementation details — rigor tests (deleted when they ship)
Part 1 — scientific-rigor tests:
- CV-windowing no-lookahead (complements the feature-level tests, which cover lag leakage but
not window construction): assert no training row has
valid_time >= val_startfor its fold — i.e. the training windowtrained_cv_modelbuilds fromfold.train_startandfold.train_endnever bleeds into validation. - Leaderboard fairness: two different experiments over the same fold are scored on the
identical
(time_series_id, fold)population — a regression guard on the experiment-independence ofeligible_time_series. - Determinism: training a fold twice with a fixed
random_seedyields identical predictions. Determinism underpins idempotent retries and a stable leaderboard.test_random_seed_makes_training_deterministicexists and evidences this at the forecaster level — it trains anXGBoostForecastertwice directly on an in-memory frame. But it never goes throughtrained_cv_modelor fold-window loading, so the fold-level claim above is not evidenced by it and remains one of the guardrail tests below that are still unwritten. - Degradation smoke-tests: ablate whole input groups — NWP absent, telemetry absent, a single
weather variable nulled — and assert that a forecast is still produced for every time series, that
every value stays inside physical bounds, and that nothing explodes. These consume the scenario
vocabulary defined by the failure-scenario suite in Metrics &
Leaderboard, so they must land
alongside it rather than against an ad-hoc vocabulary of their own. They are cheap and CI-fast —
pure functions over an
AllFeaturesframe, no MLflow — and they check survival, not skill; skill under degradation is the leaderboard's job. The principle they enforce is Inherent Stability.
Part 2 — cleanup:
- Remove any remaining dead code/imports from the phased build-out.
- Split
defs/cv_assets.py(the largest module indefs/, and the complexity hotspot flagged in the 2026-07 codebase review) intocv_assets.py/production_assets.py/metric_assets.py. Thelive_forecastswork already startsproduction_assets.py; move themetricsasset and its helpers intometric_assets.pyhere. Pure logic stays inml_core.cv_helpers.
Part 3 — docs freshness pass. The permanent-docs migration from the old dagster_plan.md is
already done (July 2026): docs/architecture/ml-orchestration.md and
docs/ml_experimentation/cross-validation-folds.md capture its important ideas. What remains:
- Check
docs/against the code after the live service and monitoring land — in particular extenddocs/ml_experimentation/dagster-workflow.mdwith the live-forecast and monitoring flows, and update the "Known limitation" and MLflow-logging notes indocs/architecture/ml-orchestration.mdif the implementations diverged from the plans. - Run the ship-time triage (per the
github-issue-pr-workflowskill) on any roadmap content the live-service work implemented — e.g. flip the relevant 🚧 statuses indocs/roadmap/metrics-and-leaderboard.mdonce monitoring lands.
Verification. Full uv run pytest green from the repo root, including the full-stack
cross-process integration test; uv run pymarkdown scan (per CLAUDE.md) green on the touched
docs; grep -ri 'dagster_plan' docs/ src/ packages/ returns nothing.