Context and rules for AI agents working in this repository. Humans should start with README.md.
- Name: bikes — a production-shaped MLOps package that predicts the number of bikes available.
- Description: reference implementation for the MLOps Coding Course, generated from cookiecutter-mlops-package.
- Language: Python 3.14+ (
pyproject.toml), managed withuv. - Stack: MLflow (tracking, registry, projects, evaluation), scikit-learn, pandas, Pydantic + Pandera validation, OmegaConf YAML configs, loguru.
- Skills: the reusable practices behind this package are published as Agent Skills in mlops-coding-skills. Install them from there rather than vendoring a copy here — a copy drifts, and this repository already lost a month to proving it.
All work goes through mise (see mise.toml); git hooks (lefthook.yml) and CI call the same tasks.
- Everything:
mise run all— format, check, test, build. This is the gate; CI runs this exact task and nothing else. - Install:
mise run install— sync the virtualenv (uv sync) and install git hooks. - Format:
mise run format—ruff(import sort + format, including Python inside Markdown) anddprint(JSON/Markdown/TOML/YAML). - Check:
mise run check—rufflint,tytypes,pip-auditdeps,dprint/validate-pyproject/uv lockformat,gitleakssecrets,trivyfilesystem scan,hadolintDockerfile,actionlint+zizmorworkflows. - Test:
mise run test—pytestwith coverage (fails under 100%);mise run test:parallelis a faster, coverage-free local loop. - Build:
mise run build—uv build(wheel + sdist);mise run build:imagebuilds the Docker image. - Docs:
mise run docs—pdocAPI reference intodocs/. - MLflow jobs:
mise run projectruns every job;mise run project:run <name>runs one (confs/<name>.yaml).
A change is complete only when, locally, mise run format is clean, mise run check reports no findings, and mise run test is green with new/changed behavior covered by a test. Fix root causes — never weaken an assertion, add a skip/xfail, loosen a type, or suppress a lint error to force a green result.
- Errors with context: raise specific exceptions and chain with
raise ... from err; never use a bareexceptor silently swallow errors. - Config over hardcoding: jobs and objects are Pydantic models parsed from OmegaConf YAML in
confs/; validate and fail fast. Dataframes are validated at boundaries with Pandera schemas (core/schemas.py). - Typing: modern annotations (
list[str],X | Y); keepty checkclean.import typing as Tis the project convention. - Logging:
loguruviaLoggerService; no bare prints in library code. - MLflow: tracking and registry run on a SQLite backend (
sqlite:///mlflow.db); artifact files stay on disk under./mlruns. This is the same SQLAlchemy store shape as a production Postgres and the store the model registry is designed for, so moving up is aMLFLOW_TRACKING_URIchange, not a rewrite. Models are logged withname=and referenced bymodels:/name@aliasormodels:/name/version. - Commits: Conventional Commits (
feat:,fix:,refactor:,chore:); no attribution in commit messages. Releases usegit-cliff(see the release process).
src/bikes/— package:core/(metrics, models, schemas),io/(configs, datasets, registries, services),jobs/(tuning, training, promotion, inference, evaluations, explanations),utils/(searchers, signers, splitters), plussettings.py,scripts.py,__main__.py.confs/— one OmegaConf YAML per MLflow job;tests/—pytestsuite mirroringsrc/with fixtures inconftest.py.pyproject.toml— dependencies andruff/ty/pytestconfig;mise.toml/mise.lock— tasks and pinned, locked tools;lefthook.yml— git hooks;dprint.jsonc/trivy.yaml/cliff.toml— formatter, scanner, changelog config..github/—workflows/(ci.ymlrunsmise run all,cd.ymlpublishes docs and the image,security.ymlrescans the full history weekly),dependabot.yml,zizmor.yml,rulesets/main.json.Dockerfile/docker-compose.yml/MLproject— container image, local MLflow server, and MLflow Projects reproducible runs (--env-manager=localreuses the uv environment, so there is nopython_env.yaml).