Imported from TomKaltofen/cedh-mulligan-simulator (
AGENTS.md). Install upstream withnpx skills add TomKaltofen/cedh-mulligan-simulator. Copyright stays with the author.
AGENTS.md
Must read README.md first.
This project uses the mloda framework. Assume any given task is related to mloda.
Environment
source .venv/bin/activate
Dependencies
Use uv to install dependencies:
uv sync --all-extras
Running checks
Use tox to run all checks:
tox
Run checks from the project virtualenv:
source .venv/bin/activate && tox
tox is the required final verification step after code or dependency changes.
Running only pytest is not sufficient for completion.
Run individual checks
pytest
ruff format --check --line-length 120 .
ruff check .
mypy --strict --ignore-missing-imports .
bandit -c pyproject.toml -r -q .
Commit messages
Use Conventional Commit format for all commits so semantic versioning/release tooling can parse intent.
Do not include Co-Authored-By lines or any other mention of AI agents in commit messages.
Examples:
fix: handle empty feature setchore(deps): bump mloda to 0.4.6
Claude Code Skills
The mloda-registry provides Claude Code skills that assist with plugin development:
When helping with FeatureGroups, ComputeFrameworks, or Extenders, leverage these skills for pattern guidance and best practices.
Consider generating project-specific skills for your own plugin repository to provide tailored AI assistance for your implementation patterns and conventions.
mloda Feature Group Guides
Before building or adapting feature groups, consult the guides at: https://github.com/mloda-ai/mloda-registry/tree/main/docs/guides/
Decision Tree — Choosing a Pattern
Use 09-create-feature-group.md to pick the right pattern:
- Does it load/generate data with no dependencies? → Root Feature (01-root-features)
- Use
DataCreator({"feat_a", "feat_b"})frominput_data()for synthetic/generated data. - Keys in the
DataCreatorset must match keys in the dict returned bycalculate_feature.
- Use
- Does it transform one or more existing features? → Derived Feature (02-derived-features)
- Return dependencies from
input_features(), compute incalculate_feature(). - Default matching is by class name (e.g. class
DoubledValuematches feature"DoubledValue").
- Return dependencies from
- Should it be reusable via naming pattern (
input__operation)? → Chained Feature (03-chained-features) - Does it produce multiple output columns? → Multi-output (
~separator) (05-multi-output-features)
Core Concepts
- Options (11-options):
groupvalues are hashed and affect feature resolution.contextvalues are metadata only. Nested dicts (like card registries) must go incontext, notgroup. - calculate_feature() (12-calculate-feature): Receives
data(DataFrame/dict with dependencies computed) andfeatures(FeatureSet with requested features, options, filters). - Feature Naming (13-feature-naming): Class name (default),
feature_names_supported()(explicit set), orPREFIX_PATTERN(regex). Separators:__(chain),~(multi-output),&(multi-input). - Feature Matching (14-feature-matching): Priority order — input data match → exact class name → prefix match → explicit names. Exactly one FeatureGroup must match per feature name.
Testing Strategy
Follow the 3-level approach from 10-testing-guide:
- Unit (fast): Test
match_feature_group_criteria(),input_features(), config methods. - Framework (medium): Test
calculate_feature()with real DataFrames. - Integration (slow): Test full pipeline via
mloda.run_all().
All Pattern Guides
| Pattern | Guide |
|---|---|
| Root features (data sources) | 01-root-features |
| Simple derived features | 02-derived-features |
Chained features (input__op) |
03-chained-features |
Multi-input features (a&b__op) |
04-multi-input-features |
Multi-output features (feat~N) |
05-multi-output-features |
| Artifact features (fitted state) | 06-artifact-features |
| Index features (time/group-by) | 07-index-features |
| Links/Joins | 08-links-joins |
| Framework-specific | 09-framework-specific |
| Testing guide | 10-testing-guide |
| Options (group vs context) | 11-options |
| calculate_feature() | 12-calculate-feature |
| Feature naming | 13-feature-naming |
| Feature matching | 14-feature-matching |
| Filter concepts | 15-filter-concepts |
| Validators | 16-validators |
| Data connection matching | 17-data-connection-matching |
| Data types | 18-datatypes |
| Domain disambiguation | 19-domain |
| Versioning | 20-versioning |
| Experimental shortcuts | 21-experimental-shortcuts |
| Feature config (JSON/AI) | 22-feature-config |
Plugin Journey Guides
| Guide | When to Use |
|---|---|
| 01-use-existing-plugin | Using plugins from the registry |
| 02-discover-plugins | Finding available plugins |
| 03-create-plugin-in-project | Adding feature groups inline (no separate package) |
| 04-create-plugin-package | Packaging plugins for distribution |
| 05-share-with-team | Sharing via private git repo |
| 06-publish-to-community | Publishing to community registry |