PhysLink — Contribution Guide
Code Quality Standards
Linting
ruff check src/
ruff check --fix src/ # auto-fix where possible
Rules active: E, F, W, I, N, UP, ANN, RUF — includes annotations (ANN) and NumPy/Ruff-specific rules (RUF). Excludes _bmad*, .venv, dist, build.
Type Checking
mypy --strict src/physlink/core/ # strict on core/
adapters/ and utils/ run with ignore_missing_imports = true and strict = false (PyTorch/matplotlib stubs are incomplete — tracked in ADR-002, deferred to v0.3.0).
Docstrings
All public classes and functions must have Google-style docstrings with:
- One-line summary
- Args: section (all parameters documented)
- Returns: section
- Raises: section (all exceptions documented)
- Example: section with a working code snippet
Error Messages
All PhysLinkError subclass messages must follow the Got/Expected/Fix template:
Got: <what was actually received>
Expected: <what was expected>
Fix: <actionable instruction>
Import Discipline
Core layer (core/): no ML framework imports anywhere, including inside functions.
Adapters/utils: torch, matplotlib, PIL, etc. must be imported inside function bodies only. Never at module level.
Pre-commit Hooks
Install on first setup:
pre-commit install
Hooks configured (.pre-commit-config.yaml):
- ruff (v0.4.10, pinned) — lint with auto-fix
- ruff-format — formatting
Pull Request Process
-
Ensure
test-cpuCI passes locally:bash ruff check src/ mypy --strict src/physlink/core/ pytest -m "not gpu" tests/ -v mkdocs build --strict -
For changes to public API: update
CHANGELOG.mdunder[Unreleased]. -
For breaking changes, use the standard format in
CHANGELOG.md: ```markdown ⚠️ Breaking: descriptionMigration: migration instructions ```
-
For test additions: maintain coverage of
core/boundaries. Integration tests intests/integration/often verify file content (README, CHANGELOG, docs) — update them when those files change. -
For new adapters: follow the adapter addition guide in
development-guide.md.
Commit Conventions
feat: new user-facing feature
fix: bug fix
chore: maintenance, tooling, release
docs: documentation only
test: test additions or corrections
refactor: non-breaking internal restructuring
GPU Testing
GPU tests (@pytest.mark.gpu) run on self-hosted T4 in CI (tag-triggered). For local GPU testing:
pytest -m "gpu" tests/ -v
If you change performance-sensitive code, run benchmarks against the baseline:
pytest tests/perf/ \
--benchmark-compare=tests/perf/baselines/benchmark_baseline.json \
--benchmark-compare-fail=min:10%
If a benchmark regression is intentional, regenerate the baseline on a T4 GPU and commit it (preserving "hardware": "T4 GPU" annotation).
Versioning
PhysLink follows Semantic Versioning:
- MAJOR — backward-incompatible public API changes
- MINOR — new backward-compatible features
- PATCH — backward-compatible bug fixes
The public API surface is exactly the 7 symbols in physlink.__all__. Any change to their signatures is a potential breaking change.
RC Process (v0.2+)
Before each minor release, publish a release candidate tag (vX.Y.0rc1) and allow 48 hours for community testing before promoting to the final release.