Contributing

Development Setup

git clone https://github.com/yourusername/supervice.git
cd supervice
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[docs]"

Running Tests

python3 -m pytest tests/ -v

All 63 tests should pass. Tests use unittest with asyncio support.

Code Quality

All code must pass these checks before merging:

mypy --strict supervice/
ruff check supervice/
ruff format --check supervice/

Type Checking

Supervice uses mypy --strict. Rules:

  • All functions must have type annotations

  • No Any types unless absolutely necessary

  • No type: ignore or @ts-expect-error suppressions

  • Union types use X | Y syntax (Python 3.10+)

Linting

Ruff is configured with these rule sets:

Rule Set

Description

E

pycodestyle errors

F

pyflakes

W

pycodestyle warnings

I

isort (import sorting)

N

pep8-naming

UP

pyupgrade

B

flake8-bugbear

Line length: 100 characters.

Project Structure

supervice/
├── supervice/          # Source code
│   ├── __init__.py
│   ├── main.py         # Daemon entry point
│   ├── core.py         # Supervisor orchestrator
│   ├── process.py      # Process lifecycle
│   ├── config.py       # Config parser
│   ├── models.py       # Data models
│   ├── events.py       # EventBus
│   ├── rpc.py          # RPC server
│   ├── client.py       # CLI client
│   ├── health.py       # Health checks
│   └── logger.py       # Logging
├── tests/              # Test suite
├── docs/               # Sphinx documentation
├── pyproject.toml      # Project config
├── README.md
└── LICENSE

Making Changes

Adding a Configuration Option

  1. Add the field to the appropriate dataclass in models.py

  2. Parse it in config.py (add validation if needed)

  3. Use it in process.py or core.py

  4. Add tests

  5. Update documentation

Adding an RPC Command

  1. Add the command name to VALID_COMMANDS in rpc.py

  2. Add a handler in RPCServer.process_request()

  3. Add a CLI subcommand in client.py

  4. Add a method to the Controller class

  5. Add tests

  6. Update documentation

Adding a Process State

  1. Define the state constant in process.py

  2. Add the corresponding EventType in events.py

  3. Add the state mapping in Process._change_state()

  4. Update state transition logic in Process.supervise()

  5. Add tests

  6. Update documentation

Constraints

  • Zero dependencies — Do not add external packages. Use stdlib only.

  • Python 3.10+ — Use modern syntax (match, X | Y unions, etc.)

  • Unix-only — No Windows compatibility needed

  • Async-first — All I/O must use asyncio

Building Documentation

cd docs
make html

Output is in docs/_build/html/. Open index.html in a browser.

Code Style Tips

  • Prefer % string formatting over f-strings (existing codebase convention for log messages)

  • Use shlex.split() for command parsing

  • Use asyncio.wait_for() with timeouts, never bare await on external I/O

  • Process groups: always os.killpg() instead of process.kill()