diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7c00a166..0ae02c2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,6 +95,13 @@ CC=gcc uv pip install --python-version=3.14 -e '.[full]' --group check --group d uv run pre-commit install ``` +## Working with agents + +We encourage contributors to use AI agents when contributing to TorchJD, but there are a few rules: +- The initiative should come from a human. We do not want PRs from fully automated bots. +- The changes should be reviewed by a human before a non-draft PR is open. +- To avoid vendor lock-in, we do not provide any file that is specific to an agent vendor. To use a specific agent that does not follow open file naming conventions, you have to adapt a few things yourself (e.g. symlink files). For example, to work with claude, you have to symlink `CLAUDE.md` to `AGENTS.md`, and `.claude/skill/` to `skills/`. + ## Checks ### Running tests @@ -275,26 +282,3 @@ The three plot scripts produce PDFs saved to `tests/trajectories/results/ [!NOTE] > The plot scripts require a LaTeX installation for rendering: > `sudo apt-get install texlive-latex-extra texlive-fonts-recommended dvipng cm-super` - - -## Release - -*This section is addressed to maintainers.* - -To release a new `torchjd` version, you have to: -- If the release introduces changes to the interface, make sure that `README.md` reflects those - changes. -- Make sure that all tests, including those on cuda, pass (for this, you need access to a machine - that has a cuda-enabled GPU). -- Make sure that all important changes since the last release have been reported in the - `[Unreleased]` section at the top of the changelog. -- Add a `[X.Y.Z] - yyyy-mm-dd` header in the changelog just below the `[Unreleased]` header. -- Change the version in `pyproject.toml`. -- Make a pull request with those changes and merge it. -- Make a draft of the release on GitHub (click on `Releases`, then `Draft a new release`, then fill - the details). -- Publish the release (click on `Publish release`). This should trigger the deployment of the new - version on PyPI and the building and deployment of the documentation on github-pages. -- Check that the new version is correctly deployed to PyPI, that it is installable and that it - works. -- Check that the documentation has been correctly deployed. diff --git a/skills/check-release/SKILL.md b/skills/check-release/SKILL.md new file mode 100644 index 00000000..8a4a5a5a --- /dev/null +++ b/skills/check-release/SKILL.md @@ -0,0 +1,103 @@ +--- +name: check-release +description: Verifies that a TorchJD release was published correctly by checking the docs site, installing from PyPI, and smoke-testing newly added classes. Use after a release has been merged and published. +--- + +# Check TorchJD Release + +This skill verifies that a release is live and correct after it has been published. + +**For agents:** invoke as `/check-release X.Y.Z` (e.g. `/check-release 0.16.0`). +If no version is provided, read the current version from `pyproject.toml`. + +--- + +## Instructions + +### Step 1: Determine the version + +Read `pyproject.toml` to find the `version` field under `[project]`. Use the version provided as +an argument, or the one from `pyproject.toml` if none is given. + +### Step 2: Identify newly added classes + +Read `CHANGELOG.md` and find the `## [X.Y.Z]` section. Extract the names of any newly added +public classes, functions, or methods listed under `### Added`. You will use these in later steps. + +### Step 3: Check the docs site + +Fetch `https://torchjd.org`. + +- Verify that the versions dropdown (or switcher) includes `vX.Y.Z` as an entry. +- Verify that the `stable` entry is present. + +If the version entry is missing, report it and stop — the rest of the checks depend on the docs +being live. + +### Step 4: Verify the new-version docs contain the newly added classes + +For each newly added class or function identified in Step 2, fetch its expected docs page under +`https://torchjd.org/vX.Y.Z/`. Use the URL patterns from similar existing classes found in +`README.md` or by browsing the stable docs (`https://torchjd.org/stable/`) to infer the correct +path (e.g. `https://torchjd.org/vX.Y.Z/docs/aggregation`, +`https://torchjd.org/vX.Y.Z/docs/scalarization`, etc.). + +Confirm that each new class/function name appears on the fetched page. + +### Step 5: Verify the stable docs also reflect the new version + +Fetch the same doc pages under `https://torchjd.org/stable/` and confirm the newly added +classes/functions appear there too (i.e. `stable` points to the new release). + +### Step 6: Install torchjd from PyPI in a temp environment + +Run the following commands to create an isolated install: + +```bash +cd /tmp && mkdir -p test_torchjd_install && cd test_torchjd_install +uv venv && uv pip install torchjd +``` + +Verify the installed version matches X.Y.Z: + +```bash +cd /tmp/test_torchjd_install && uv pip show torchjd +``` + +If the version is wrong, report it and stop. + +### Step 7: Smoke-test the newly added classes + +Write a minimal Python script `/tmp/test_torchjd_install/smoke_test.py` that: + +- Imports each newly added class or function by its fully-qualified name from `torchjd`. +- Instantiates or calls each one with a minimal valid input (e.g. a small `torch.Tensor`, a dummy + preference vector, or no arguments if the class takes none). +- Does NOT assert correctness of values — only that the code runs without raising an exception. + +Use the existing test suite under `tests/` or the docs pages fetched in Step 4 as a reference for +correct import paths and minimal usage patterns. + +Run the script: + +```bash +cd /tmp/test_torchjd_install && uv run python smoke_test.py +``` + +Report the result. If it crashes, show the traceback. + +### Step 8: Clean up + +```bash +rm -rf /tmp/test_torchjd_install +``` + +### Step 9: Report + +Summarize what was verified: +- Docs site: version dropdown ✓/✗, new-version page ✓/✗, stable page ✓/✗ +- PyPI install: version matches ✓/✗ +- Smoke test: each newly added class ✓/✗ (list them) + +If everything passes, the release is confirmed good. If anything failed, describe what needs +attention. diff --git a/skills/prepare-release/SKILL.md b/skills/prepare-release/SKILL.md new file mode 100644 index 00000000..788361d6 --- /dev/null +++ b/skills/prepare-release/SKILL.md @@ -0,0 +1,97 @@ +--- +name: prepare-release +description: Prepares a torchjd package release by verifying the changelog, README, bumping the version in pyproject.toml, and opening a release PR. Use when a maintainer asks to prepare a release or to release. +--- + +# Prepare TorchJD Release + +This skill covers the pre-merge steps of the release process. + +**For agents:** invoke as `/prepare-release X.Y.Z` (e.g. `/prepare-release 0.16.0`). +If no version is provided, read the current version from `pyproject.toml` and ask the user +what the new version should be before proceeding. + +**For humans:** follow the numbered steps below in your terminal. +Replace `X.Y.Z` with the version you are releasing and `yyyy-mm-dd` with today's date. + +--- + +## Instructions + +### Step 1: Determine the version + +Read `pyproject.toml` to find the current `version` field under `[project]`. The new release +version is either provided as an argument or must be confirmed with the user before continuing. + +Verify it follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +### Step 2: Verify CHANGELOG + +Read `CHANGELOG.md` and compare it against the commits done since the last version release. Verify that no user-facing change was forgotten, and that all were correctly added under the [Unreleased] section. + +### Step 3: Check README for interface changes + +Read `CHANGELOG.md` and identify any entries in the `[Unreleased]` section that affect the public +interface (new or removed classes, functions, or arguments; changed signatures or behavior). + +If such entries exist, read `README.md` and verify it accurately describes the current interface. + +If a table listing methods exists in `README.md`, add to it any newly added method of the corresponding type. + +If anything else seems missing, report that to the user. + +### Step 4: Run the unit tests + +CRITICAL: Do not skip this step, even partially. + +Run the unit tests and confirm they all pass both on CPU and GPU (you need a CUDA-enabled GPU for this): + +```bash +uv run pytest tests/unit +PYTEST_TORCH_DEVICE=cuda:0 uv run pytest tests/unit +``` + +If any tests fail, stop and report the failures. Do not proceed to the next steps. + +### Step 5: Add the version header to the changelog + +In `CHANGELOG.md`, insert a new `## [X.Y.Z] - yyyy-mm-dd` heading immediately after the blank +line that follows `## [Unreleased]`, before the existing subsections: + +```diff + ## [Unreleased] + ++## [X.Y.Z] - yyyy-mm-dd ++ + ### Added +``` + +The `[Unreleased]` section stays in place and will accumulate entries for the next release. +The newly-inserted heading claims the existing content as its own. + +### Step 6: Bump the version in `pyproject.toml` + +In `pyproject.toml`, update the `version` field under `[project]`: + +```diff +-version = "A.B.C" ++version = "X.Y.Z" +``` + +### Step 7: Open the release PR + +Stage changes, then open a pull request targeting `main`. +Return the PR URL when done. + +### Step 8: Create a draft release on GitHub + +CRITICAL: The release you'll create should ALWAYS be a draft. Never even suggest to make the real release. A maintainer will manually release the draft if it seems ready. + +The command should be: +``` +gh release create vX.Y.Z --draft --title vX.Y.Z --notes "" +``` + +To write the actual release notes, look at what is done in recent releases and suggest the new notes. Make it short. Also, prompt the user for a good-looking emoji (propose a list) to use in the main section of the release notes. + +---