Check¶
Definition¶
Check is a small frozen dataclass representing the outcome of a single preflight path-existence test. A collection of Check objects is passed to run_preflight(), which logs each result and raises SystemExit on the first critical failure. Check objects are produced by check_path_exists() and consumed exclusively by run_preflight().
Kind¶
Value object (@dataclass, four fields). Immutable by convention (no frozen=True in the dataclass decorator, but no mutation after construction occurs in the codebase).
Source of truth¶
run/preflight.py:20 — class Check.
@dataclass
class Check:
"""Result of a single preflight check."""
name: str
passed: bool
message: str = ""
critical: bool = False
Key attributes¶
| Field | Type | Default | Semantics |
|---|---|---|---|
name |
str |
— | Human-readable identifier, typically "path_exists:<path>" |
passed |
bool |
— | True if the check succeeded |
message |
str |
"" |
Diagnostic detail; empty on success, "Path not found: <path>" on failure |
critical |
bool |
False |
When True and passed=False, run_preflight() raises SystemExit |
Lifecycle¶
check_path_exists(path)(preflight.py:30) wrapsAnyPath(str(path)).exists()(cloud-safe) and returns aCheckwithcritical=True.- Stage-specific functions (see below) build
list[Check]by callingcheck_path_existsfor each required path. run_preflight(checks)(preflight.py:42) iterates the list, logs atSUCCESS/WARNING/ERROR, and raisesSystemExiton the first critical failure.
The five stage-specific check-sets¶
Each function in run/preflight.py returns a list[Check] tailored to one pipeline stage:
| Function | Stage | What it checks |
|---|---|---|
preflight_paths_for_features |
run_features |
All ResolvablePath inputs (stress parquet omitted when assembled from indices) |
preflight_paths_for_hindcast |
run_hindcast / run_fit_production |
check_data_exists entries + fit.parquet + pred.parquet under features_dir |
preflight_paths_for_forecast_features |
run_forecast_features |
Resolvable inputs + canonical hindcast pred.parquet |
preflight_paths_for_forecast_predict |
run_forecast_predict |
Resolvable inputs + per-(season_year, init_date) forecast features parquet + detrender.pkl + feature_fill_values.parquet |
preflight_paths_for_export |
run_export |
Resolvable inputs only |
preflight_paths_for_forecast (preflight.py:183) is a convenience composer that returns the union of preflight_paths_for_forecast_features and preflight_paths_for_forecast_predict; it is not a sixth independent check-set.
preflight_paths_for_resolvable_inputs (preflight.py:77) is a shared helper called by several of the above; it mechanically walks _iter_resolvable_fields(config) so any new ResolvablePath field is automatically covered without a hand-maintained list.
Relationships¶
- Produced by:
check_path_exists(preflight.py:30) - Consumed by:
run_preflight(preflight.py:42) - Assembled by: the five stage-specific functions above
- Called from:
cli.pyentry points (e.g.run_features_cmdcallspreflight_paths_for_features),delivery/export.py:run_export(callsrun_preflight(preflight_paths_for_export(config)))
Package layering caveats¶
The Check entity itself is innocent of any layering violation. Two import-direction issues exist in the surrounding package:
delivery/export.py:39importspreflight_paths_for_exportandrun_preflightfromrun/preflight.py. Therun/package is an orchestration-level module; Delivery should not depend on it directly. Correct home: migratepreflight_paths_for_exporttolib/.delivery/conversions.py:50importsprimary_calibrationfromstages/run_meta_models.py. Delivery should not depend on Stages. Correct home:lib/conformal/.
Both violations are non-breaking at runtime but contradict the single-direction import rule in DESIGN.md:49 and complicate isolated testing of the Delivery subsystem.
Open questions¶
- All current checks are path-existence checks with
critical=True. Thecritical=False/ warning path is plumbed but never exercised. Non-critical checks (e.g. config-value sanity) could be added without changing the interface.