This runbook covers build, validation, and incident recovery for the V1 forecaster pipeline.
- Build artifacts:
python scripts/build_forecaster_v1.py --input data/raw/hdb_resale_2017_onwards.csv
- Verify reproducibility smoke check:
python scripts/verify_forecaster_repro.py
- Run quality gates:
make ruffmake testpython -m pip_audit -r requirements.txtpython scripts/run_forecaster_near_term_eval.py --input data/raw/hdb_resale_2017_onwards.csv
- Materialize governed feedback datasets:
python scripts/prepare_feedback_dataset.py
- (Optional) refresh official MRT references:
make fetch-mrt-reference
- (Optional) refresh official MRT-to-CBD travel-time features:
make fetch-mrt-travel-times- Credentials required:
- local: repo-root
.env(ONEMAP_API_EMAIL,ONEMAP_API_PASSWORD) - Streamlit Cloud: App Settings -> Secrets with same keys
- local: repo-root
Use this command to run the full machine-learning path without opening Streamlit:
ML_OPEN_STREAMLIT=0 ML_RUN_DEEPCHECKS=1 RUN_ALL_SKIP_INSTALL=1 ./run-all-machinelearning.shExpected phases:
- environment/bootstrap,
- lint + tests,
- artifact build,
- Deepchecks validation stage,
- inference smoke-check,
- vulnerability audit.
Near-term eval release criteria:
- rolling windows must satisfy configured minimum (
validation.rolling_min_windows), - promotion gate in
near_term_eval.jsonmust reportpass=true, - if gate fails, do not promote artifacts without documented exception.
- enforce hard failure in CI/release jobs with
python scripts/run_forecaster_near_term_eval.py --input ... --enforce-gate.
- Model artifact:
models/forecaster_v1/model.joblib - Metadata:
models/forecaster_v1/metadata.json - Config snapshot:
models/forecaster_v1/train_config.json - Model card:
models/forecaster_v1/model_card.md - Near-term evaluation:
reports/forecaster_v1/near_term_eval.{json,md} - Official MRT references:
data/reference/mrt_station_symbol_ura.geojson - Official MRT name annotations:
data/reference/mrt_masterplan2003_name_ura.geojson - Official MRT travel-time features:
data/reference/mrt_travel_time_to_cbd.csv
Expected metadata fields include:
- split windows and counts,
- aggregate and segment metrics,
- source file provenance (
source_path,source_sha256,ingested_at_utc), - training configuration.
- Symptom: missing
libomp.dylib. - Fix:
brew install libomp.
- Ensure both files exist:
models/forecaster_v1/model.joblibmodels/forecaster_v1/metadata.json
- Re-run builder command if either file is missing.
- Check inference inputs are valid (positive area/lease and known categoricals).
- Rebuild artifacts to refresh feature map:
python scripts/build_forecaster_v1.py --input data/raw/hdb_resale_2017_onwards.csv
- Re-run smoke check:
python scripts/verify_forecaster_repro.py
- Confirm source dataset hash changed (
metadata.jsonprovenance block). - Compare current vs previous metrics JSON snapshots.
- Validate ingestion schema did not change unexpectedly.
- Roll back to prior known-good artifact set if needed.
- Inspect
reports/forecaster_v1/near_term_eval.json:rolling_origin.overall_interval_coverage_p10_p90rolling_origin.mean_interval_widthpromotion_gate
- Compare against config thresholds in
configs/forecaster_v1.yaml. - If width is high or coverage is low, retrain with updated features/hyperparameters and rerun eval.
- Keep previous artifact set as active until the gate passes.
- Check for fallback file:
reports/deepchecks/forecaster_v1/deepchecks_unavailable.txt
- This indicates environment-level incompatibility in upstream Deepchecks dependencies.
- Keep training pipeline running, but treat Deepchecks as degraded until dependency compatibility is resolved.
- Current baseline is
mlflow>=3.11.1,<4inpyproject.toml. - Tracking backend default is
sqlite:///mlflow.db(configured inconfigs/forecaster_v1.yaml) to avoid deprecated filesystem backend warnings. - If
pip-auditreports new MLflow vulnerabilities:- upgrade to remediated line,
- rebuild environment,
- re-run
python -m pip_audit -r requirements.txt. - record findings/remediation in release notes.
400 Bad Requestduring auth:- verify
.envor secrets keys are present and not placeholder values.
- verify
401/403during routing:- refresh credentials/token and retry.
404for route edge case:- script now guards self-anchor routing and should not fail on identical start/end.
- Re-run materialization:
python scripts/prepare_feedback_dataset.py. - Validate outputs:
data/feedback/forecaster_feedback_validated.csvdata/feedback/forecaster_feedback_retraining.csv
- Ensure retention and comment redaction settings are correct in
configs/forecaster_v1.yaml.