From 82acb15c3b547733c761c1ecf263b8215db016a7 Mon Sep 17 00:00:00 2001 From: "Benjamin T. Vincent" Date: Tue, 11 Nov 2025 21:10:59 +0000 Subject: [PATCH 1/2] first stab at an AGENTS.md file --- AGENTS.md | 29 +++++++++++++++++++++++++++++ CONTRIBUTING.md | 3 +++ 2 files changed, 32 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..8ab9cd68 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,29 @@ +# AGENTS + +## Testing preferences + +- Write all Python tests as `pytest` style functions, not unittest classes +- Use descriptive function names starting with `test_` +- Prefer fixtures over setup/teardown methods +- Use assert statements directly, not self.assertEqual + +## Testing approach + +- Never create throwaway test scripts or ad hoc verification files +- If you need to test functionality, write a proper test in the test suite +- All tests go in the `causalpy/tests/` directory following the project structure +- Tests should be runnable with the rest of the suite (`python -m pytest`) +- Even for quick verification, write it as a real test that provides ongoing value +- Preference should be given to integration tests, but unit tests are acceptable for core functionality to maintain high code coverage. +- Tests should remain quick to run. Tests involving MCMC sampling with PyMC should use custom `sample_kwargs` to minimize the computational load. + +## Documentation + +- **Structure**: Notebooks (how-to examples) go in `docs/source/notebooks/`, knowledgebase (educational content) goes in `docs/source/knowledgebase/` +- **Notebook naming**: Use pattern `{method}_{model}.ipynb` (e.g., `did_pymc.ipynb`, `rd_skl.ipynb`), organized by causal method +- **MyST directives**: Use `:::{note}` and other MyST features for callouts and formatting +- **Glossary linking**: Use Sphinx `:term:` directives to link to glossary terms (defined in `glossary.rst`), typically on first mention in a file +- **Citations**: Use `references.bib` for citations, cite sources in example notebooks where possible. Include reference section at bottom of notebooks using `:::{bibliography}` directive with `:filter: docname in docnames` +- **API documentation**: Auto-generated from docstrings via Sphinx autodoc, no manual API docs needed +- **Build**: Use `make html` to build documentation +- **Doctest**: Use `make doctest` to test that Python examples in doctests work diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 762f82c8..a0bb3962 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,9 @@ We appreciate being notified of problems with the existing CausalPy code. We pre Please verify that your issue is not being currently addressed by other issues or pull requests by using the GitHub search tool to look for key words in the project issue tracker. +## Use of agents +PR's with agent-generated code are fine. But don't spam us with code you don't understand. See [AGENTS.md](./AGENTS.md) for how we use LLMs in this repo. + ## Contributing code via pull requests While issue reporting is valuable, we strongly encourage users who are inclined to do so to submit patches for new or existing issues via pull requests. This is particularly the case for simple fixes, such as typos or tweaks to documentation, which do not require a heavy investment of time and attention. From ee8ff1ccf6b95f368fdcc553284ae6f6c96a8e1b Mon Sep 17 00:00:00 2001 From: "Benjamin T. Vincent" Date: Tue, 11 Nov 2025 21:43:38 +0000 Subject: [PATCH 2/2] Add "code structure and style" section --- AGENTS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 8ab9cd68..5bc7c16e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,3 +27,13 @@ - **API documentation**: Auto-generated from docstrings via Sphinx autodoc, no manual API docs needed - **Build**: Use `make html` to build documentation - **Doctest**: Use `make doctest` to test that Python examples in doctests work + +## Code structure and style + +- **Experiment classes**: All experiment classes inherit from `BaseExperiment` in `causalpy/experiments/`. Must declare `supports_ols` and `supports_bayes` class attributes. Only implement abstract methods for supported model types (e.g., if only Bayesian is supported, implement `_bayesian_plot()` and `get_plot_data_bayesian()`; if only OLS is supported, implement `_ols_plot()` and `get_plot_data_ols()`) +- **Model-agnostic design**: Experiment classes should work with both PyMC and scikit-learn models. Use `isinstance(self.model, PyMCModel)` vs `isinstance(self.model, RegressorMixin)` to dispatch to appropriate implementations +- **Model classes**: PyMC models inherit from `PyMCModel` (extends `pm.Model`). Scikit-learn models use `RegressorMixin` and are made compatible via `create_causalpy_compatible_class()`. Common interface: `fit()`, `predict()`, `score()`, `calculate_impact()`, `print_coefficients()` +- **Data handling**: PyMC models use `xarray.DataArray` with coords (keys like "coeffs", "obs_ind", "treated_units"). Scikit-learn models use numpy arrays. Data index should be named "obs_ind" +- **Formulas**: Use patsy for formula parsing (via `dmatrices()`) +- **Custom exceptions**: Use project-specific exceptions from `causalpy.custom_exceptions`: `FormulaException`, `DataException`, `BadIndexException` +- **File organization**: Experiments in `causalpy/experiments/`, PyMC models in `causalpy/pymc_models.py`, scikit-learn models in `causalpy/skl_models.py`