Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
python-version: ["3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,9 @@ shortcuts.
written those files since; the build stamped four empty registries out and the runtime
spread four empty objects into the maps the plugins already filled. The comments claiming
the registries held `ts_src` terms described the design they replaced.
- **Python 3.10.** `requires-python` is `>=3.11`. 3.10 reached its end of life this month,
and the fixes for the Pillow and filelock advisories (Pillow 13, filelock 4.2.1) require
3.11, so a 3.10 install could only resolve the vulnerable releases.

### Fixed

Expand Down Expand Up @@ -1209,3 +1212,6 @@ shortcuts.
where they used to fetch the CPU wheel outside the lock.
- **Every GitHub Action is pinned to a commit SHA**, with its release tag in a comment: a
moved tag no longer changes what a workflow runs.
- **Pillow 13.0.0, filelock 4.2.4 and virtualenv 21.14.12 in `uv.lock`**, for the
Dependabot advisories against Pillow < 13.0.0, filelock 3.20.4 to 4.2.0 and virtualenv
< 21.14.10.
4 changes: 2 additions & 2 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ Key Makefile targets: `sync`, `format`, `type`, `check`, `test`, `test-all`, `do

`@pytest.mark.slow` triggers a full frontend (npm + Vite) build and is excluded from pre-commit (`pytest -m "not slow"`); unmarked tests are fast and always run.

Workflows: `pytest.yml` runs `pytest -m "not slow"` across Python 3.10 / 3.11 / 3.12 / 3.13 with the `dev` extra only, and a `core` job installs mjswan with no extra to run `tests/test_core_install.py` (import, a model-only build, and the extra each source names), which skips anywhere an extra is installed. `parity.yml` is separate and heavier: it installs the `examples` extras, caches warp's CPU kernels, and runs the ONNX numeric-parity sweep over the reference mjlab tasks on `workflow_dispatch`, on a pull request that touches `compile/`, `build/mdp/`, `mjlab/env.py`, the parity tests or `uv.lock`, and weekly. Weekly because that cadence targets *upstream* drift: mjlab moves fast, and a changed term definition would otherwise surface as a mysterious runtime difference rather than a failing check. `frontend.yml` lints the template and runs its vitest suite, sharing one dependency install. `release.yml` writes one version into `_version.py`, `package.json` and `package-lock.json`, commits it to main for a stable release, tags it, and calls `publish-pypi.yml` and `publish-npm.yml`, which set the version from the input again so a prerelease needs no commit. Also: `ruff.yml`, `deploy.yml`, `sync-contributors.yml`.
Workflows: `pytest.yml` runs `pytest -m "not slow"` across Python 3.11 / 3.12 / 3.13 with the `dev` extra only, and a `core` job installs mjswan with no extra to run `tests/test_core_install.py` (import, a model-only build, and the extra each source names), which skips anywhere an extra is installed. `parity.yml` is separate and heavier: it installs the `examples` extras, caches warp's CPU kernels, and runs the ONNX numeric-parity sweep over the reference mjlab tasks on `workflow_dispatch`, on a pull request that touches `compile/`, `build/mdp/`, `mjlab/env.py`, the parity tests or `uv.lock`, and weekly. Weekly because that cadence targets *upstream* drift: mjlab moves fast, and a changed term definition would otherwise surface as a mysterious runtime difference rather than a failing check. `frontend.yml` lints the template and runs its vitest suite, sharing one dependency install. `release.yml` writes one version into `_version.py`, `package.json` and `package-lock.json`, commits it to main for a stable release, tags it, and calls `publish-pypi.yml` and `publish-npm.yml`, which set the version from the input again so a prerelease needs no commit. Also: `ruff.yml`, `deploy.yml`, `sync-contributors.yml`.

Every workflow installs Python dependencies from `uv.lock` alone (`uv sync --locked`, `uv run --locked`), so a release published since the last lock never reaches CI, torch included: the locked Linux wheel is the CUDA build. The `core` job's pytest is the `test` dependency group, locked like an extra but not published as one. `[tool.uv] exclude-newer = "3 days"` keeps a release out of the lock until it is three days old, the window in which hijacked releases have been caught and pulled; to take a younger one deliberately, name it in `[tool.uv] exclude-newer-package` (passed on the command line instead, it leaves a lock that `--locked` rejects). Every action is pinned to a commit SHA with its release tag beside it.

Expand All @@ -313,7 +313,7 @@ Extras, one per asset source plus tooling: `wandb`, `hf` (`huggingface-hub`), `m

The core `mujoco` pin is exact and follows mjlab's, which is what lets `mjswan[mjlab]` resolve at all: mjlab 1.6.0 requires `mujoco~=3.11.0` and brings `mujoco-warp` with it. Holding the core at 3.8.1 while mjlab moved to 3.10 and then 3.11 is what the `[tool.uv] override-dependencies` block existed for; aligning the pin retired it, and with it the resolution that only ever worked inside this repo. The browser's own engine is the template's `mujoco` dependency, an alias pinned to `@ttktjmt/mujoco` at the same version: a `.mjz` carries MJCF the browser compiles itself, but a scene saved as `.mjb` loads only in the MuJoCo that wrote it. `tests/test_dependency_versions.py` holds the two pins together and `src/engine/__tests__/mujocoPackage.test.ts` checks the alias is what installs. The alias is a fork because MuJoCo's own `@mujoco/mujoco` throws on every `mjtBool` array from 3.9.0 on; `@ttktjmt/mujoco` is 3.11.0 with the generator fix of google-deepmind/mujoco#3616, and the alias goes back to `@mujoco/mujoco` once a release carries it and mjlab's pin reaches that release. The template's `.npmrc` refuses any package younger than three days (`min-release-age`), which a fresh fork release is: its lockfile entry was written with that check off once, and `npm install` and `npm ci` then install from the lockfile without it.

Python 3.10 to 3.13. The old `<3.13` cap was taken for `labmaze` (transitive via myosuite →
Python 3.11 to 3.13; 3.10 went at its end of life, when Pillow 13 and filelock 4.2 (the fixes for their advisories) required 3.11. The old `<3.13` cap was taken for `labmaze` (transitive via myosuite →
dm-control, no cp313 wheel); myosuite left with the #128 examples cleanup, so the cap and
the `h5py` override beside it are gone and the pytest matrix runs 3.13.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ mjswan can be installed as a Python package (the primary workflow) or as an npm

| Requirement | Version |
|---|---|
| Python | 3.10 to 3.13 |
| Python | 3.11 to 3.13 |
| Platform | macOS (Apple Silicon) or Linux (x86-64) |
| Browser | Any modern browser with WebAssembly and WebGL |
| Node.js | 24+ (npm installation only) |
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/skills/mjlab-to-mjswan.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ a browser app.

## Requirements

- `git` and Python 3.10 to 3.13. The agent installs mjswan itself. No GPU needed.
- `git` and Python 3.11 to 3.13. The agent installs mjswan itself. No GPU needed.
- Checkpoints: a W&B run, a Hugging Face repository, or `model_*.pt` files.

!!! warning
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ authors = [
description = "Browser-based MuJoCo simulation with real-time policy control"
readme = "README.md"
license = { text="Apache-2.0" }
requires-python = ">=3.10"
requires-python = ">=3.11"
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
Expand Down
2 changes: 1 addition & 1 deletion skills/mjlab-to-mjswan/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Then invoke it with the target repo:

Any other agent can follow `SKILL.md` directly, it is plain Markdown with no vendor-specific syntax.

Either way the agent needs `git` and a Python 3.10-3.13 environment in which the target repo's task registrations import; it installs `mjswan[mjlab]` and `onnxruntime` into that environment itself, plus the `wandb` or `hf` extra when the checkpoints come from there.
Either way the agent needs `git` and a Python 3.11-3.13 environment in which the target repo's task registrations import; it installs `mjswan[mjlab]` and `onnxruntime` into that environment itself, plus the `wandb` or `hf` extra when the checkpoints come from there.

## The pipeline

Expand Down
Loading
Loading