|
1 | | -Thank you for wanting to contribute to PolicyEngine! :smiley: |
| 1 | +# Contributing to policyengine-uk |
2 | 2 |
|
3 | | -TL;DR: [GitHub Flow](https://guides.github.com/introduction/flow/), [SemVer](http://semver.org/). |
| 3 | +See the [shared PolicyEngine contribution guide](https://github.com/PolicyEngine/.github/blob/main/CONTRIBUTING.md) for cross-repo conventions (towncrier changelog fragments, `uv run`, PR description format, anti-patterns). This file covers policyengine-uk specifics. |
4 | 4 |
|
5 | | -## Pull requests |
| 5 | +## Commands |
6 | 6 |
|
7 | | -We follow the [GitHub Flow](https://guides.github.com/introduction/flow/): all code contributions are submitted via a pull request towards the `master` branch. |
8 | | - |
9 | | -Opening a Pull Request means you want that code to be merged. If you want to only discuss it, send a link to your branch along with your questions through whichever communication channel you prefer. |
10 | | - |
11 | | -Please make sure (if you're changing the package; you don't have to for documentation or package health changes) to add to changelog_entry.yaml and run 'make changelog', then commit the results. |
12 | | - |
13 | | -### Peer reviews |
14 | | - |
15 | | -All pull requests must be reviewed by someone else than their original author. |
16 | | - |
17 | | -> In case of a lack of available reviewers, one may review oneself, but only after at least 24 hours have passed without working on the code to review. |
18 | | -
|
19 | | -To help reviewers, make sure to add to your PR a **clear text explanation** of your changes. |
20 | | - |
21 | | -In case of breaking changes, you **must** give details about what features were deprecated. |
22 | | - |
23 | | -> You must also provide guidelines to help users adapt their code to be compatible with the new version of the package. |
24 | | -
|
25 | | -## Advertising changes |
26 | | - |
27 | | -Our versioning is currently done manually. You should: |
28 | | - |
29 | | -* Add a new entry to the changelog_entry.yaml file. See below for an example. |
30 | | -* Run 'make changelog' to update the changelog.md file. |
31 | | -* Commit and push your changes (this will have changed `CHANGELOG.md`, `changelog.yaml` and `setup.py`). |
32 | | - |
33 | | -### Example of a changelog entry |
34 | | - |
35 | | -```yaml |
36 | | -- bump: minor |
37 | | - changes: |
38 | | - added: |
39 | | - - Added this thing. |
40 | | - changed: |
41 | | - - Changed that thing. |
42 | | - fixed: |
43 | | - - Bug you fixed. |
| 7 | +```bash |
| 8 | +make install # install deps (uv) |
| 9 | +make format # format (required — CI enforces) |
| 10 | +make test # full test suite |
| 11 | +uv run policyengine-core test policyengine_uk/tests/path/to/test.yaml -c policyengine_uk |
| 12 | +uv run pytest policyengine_uk/tests/path/to/test_file.py::test_name -v |
44 | 13 | ``` |
45 | 14 |
|
46 | | -### Version number |
| 15 | +Python 3.11–3.14. Default branch: `main`. |
47 | 16 |
|
48 | | -We follow the [semantic versioning](http://semver.org/) spec: any change impacts the version number, and the version number conveys API compatibility information **only**. |
| 17 | +## Writing variables and reforms |
49 | 18 |
|
50 | | -Examples: |
| 19 | +Four types of files usually change together: |
51 | 20 |
|
52 | | -#### Patch bump |
| 21 | +| Type | Location | |
| 22 | +| --------------------- | ---------------------------------------------------------- | |
| 23 | +| YAML unit tests | `policyengine_uk/tests/policy/...` | |
| 24 | +| Parameter (`.yaml`) | `policyengine_uk/parameters/gov/<agency>/...` (DWP, HMRC, DfE, …) | |
| 25 | +| Variable (`.py`) | `policyengine_uk/variables/gov/<agency>/...` | |
| 26 | +| Changelog fragment | `changelog.d/<branch>.<type>.md` | |
53 | 27 |
|
54 | | -- Fixing or improving an already existing calculation. |
| 28 | +Conventions: |
55 | 29 |
|
56 | | -#### Minor bump |
| 30 | +- Write YAML tests **first** (TDD). They fail until the variable formula is in place. |
| 31 | +- Use `where(...)`, `max_(...)`, `min_(...)` inside formulas — never Python `if` / `max` / `min`. Vectorisation requires numpy. |
| 32 | +- Match the variable file name to the class name (e.g. `pip_dl.py` defines `class pip_dl(Variable)`). |
| 33 | +- For devolved programs, use the correct agency: |
| 34 | + - England default → `gov/dwp/` or `gov/hmrc/` or `gov/dfe/` |
| 35 | + - Scotland → `gov/social_security_scotland/` or `gov/revenue_scotland/` |
| 36 | + - Wales → `gov/senedd/` / `gov/welsh_revenue_authority/` as appropriate |
| 37 | +- Cite UK legislation in the variable's `reference` field (gov.uk, legislation.gov.uk). |
57 | 38 |
|
58 | | -- Adding a variable to the tax and benefit system. |
| 39 | +## Program registry |
59 | 40 |
|
60 | | -#### Major bump |
| 41 | +`policyengine_uk/programs.yaml` is the single source of truth for program coverage metadata and drives the `/uk/metadata` API. When adding a program, add an entry with `id`, `name`, `full_name`, `category`, `agency`, `status`, `coverage`, `variable`, `parameter_prefix`. When extending year coverage, bump `verified_years` after verifying parameters and tests cover the new year. |
61 | 42 |
|
62 | | -- Renaming or removing a variable from the tax and benefit system. |
| 43 | +## Repo-specific anti-patterns |
63 | 44 |
|
| 45 | +- **Don't change HF upload destinations** in the `policyengine-uk-data` upload pipeline without explicit authorisation — the private/public split exists to respect the UK Data Service licence. |
| 46 | +- **Don't hardcode FRS-year logic** in variable formulas; defer to `policyengine-uk-data` for dataset semantics. |
0 commit comments