Contributing to harPY
Use this guide to set up a development checkout, check a change, and submit a bug report or pull request. Start with a reproducible problem or a specific improvement to an experiment, the code, or its documentation.
The public v1 release is package 1.0.0, tagged v1. New contributions target
main; the older v1.0.0 development checkpoint retains historical interfaces. Read the
getting-started guide for the current workflow and the
v1 specification for the task and public contracts.
Set up a development checkout
Use Python 3.12 on Linux or WSL, the qualified environment, with uv installed.
Clone main for new work, or use your existing development checkout:
git clone --branch main https://github.com/williamshayden/Harpy.git
cd Harpy
uv sync --locked --group dev --python 3.12
uv run --no-sync harpy --help
For the v1 release checkout, use --branch v1 instead of --branch main.
uv sync creates .venv, installs harPY in editable mode, and installs the
locked base dependencies plus pytest and Ruff. Edits under src/ are available
without reinstalling. Run subsequent commands from the repository root.
The base environment is enough for documentation, classical actors, ordinary
result readers, and most experiment-runner work. If the change needs supervised
pitch inference or training, add --extra pitch to the sync command. For PPO,
use --extra train, which includes Torch and Stable-Baselines3. These extras can
be substantial downloads. Keep the chosen extra in later sync commands: an
exact sync removes packages outside the selected dependencies. --no-sync in
the commands below uses the environment you already prepared.
Find the relevant code
| Area | Location and purpose |
|---|---|
| Public experiment API | src/harpy/experiments/: actor specifications, episode runner, strict results, saved artifacts, and training |
| Current command line | src/harpy/cli.py: evaluate, run, summarize, and train |
| Task and observations | src/harpy/envs/: controls, planning, observation ownership, spectrum encoding, and corruption conditions |
| Audio implementation | src/harpy/synth/, analysis.py, and tuning.py under src/harpy/ |
| Learning implementation | src/harpy/learning/: shared model code and retained historical workflows/readers |
| Examples and tests | examples/custom_actor.py; tests/ broadly follows the implementation areas |
| Contracts and evidence | docs/v1-*.md describes the current package; dated verification records and research/ preserve specific experiments |
The factory-based API in harpy.experiments is the current extension point.
Historical learning modules remain useful for reading and reproducing older
work; their presence does not make every internal class a supported public API.
Check what the change affects
For Python changes, check style and run the tests closest to the behavior:
uv run --no-sync ruff check src tests examples
uv run --no-sync ruff format --check src tests examples
uv run --no-sync pytest tests/test_imports.py tests/test_cli.py \
tests/experiments/test_runner.py tests/experiments/test_results.py
git diff --check
That test selection covers imports, current CLI behavior, actor lifecycle, and
result validation. It is a useful starting point, not the full test suite. For
example, an FFT estimator change also needs tests/experiments/test_waveform_fft.py;
an artifact-loading change needs tests/experiments/test_artifacts.py.
For a documentation-only correction, check links and execute the affected
example instead of running unrelated tests. For optional training changes,
tests/experiments/test_training.py checks parameter updates from short CPU training runs, checkpoint
reload, and saved-artifact evaluation; install the relevant extra first and
report any skipped cases. GPU training and the full scientific studies are not
prerequisites for every contribution.
Add a regression test when it captures the failure or changed contract. A reader fix, for example, should reject the inconsistent result that exposed the bug. A test that merely repeats the implementation adds little evidence.
Try a custom actor
The existing example adapts waveform observations to the spectrum baseline’s decoder and controller. It runs six shared clean episodes for each actor:
uv run --no-sync python examples/custom_actor.py \
--output runs/contributor-adapter-smoke.json
uv run --no-sync harpy summarize runs/contributor-adapter-smoke.json --format markdown
Use a fresh output path when repeating it. The example introduces no new estimator claim; it shows where to substitute an encoding while holding control fixed.
An ActorSpec factory must create fresh controller state for every episode. It
can share immutable model weights. A controller’s decide(observation) returns
a Decision containing an action and, when available, a pitch estimate and
inference count. Declare the observation mode and estimator, decoder, and
controller identities accurately. These labels describe the implementation;
they do not dynamically assemble it. artifact_paths can bind custom source
or model files to the result’s recorded hashes.
Audio actors receive public waveform or spectrum observations, not the hidden source coordinate or nuisance seed. Preserve the separation between audio, reward-feedback, and oracle tracks. A new input family or task needs its own implementation and validation; a custom actor alone does not extend the single-sine environment to instruments or recordings.
For model inputs, action parsing, and configuration to record, see Evaluate a general-purpose model.
Preserve interpretable results
Keep episode membership and corruption conditions matched when comparing actors. Report initial estimation accuracy separately from submitted success, and retain partitions, conditions, seeds, invalid actions, truncations, and action/inference counts. Ordinary result readers validate records and recompute metrics; do not relax those checks just to accept a malformed fixture.
Saved results and model directories are create-only. Put new runs under ignored
runs/ or outputs/ paths, and preserve failed or interrupted artifacts when
they explain a problem. Do not rewrite frozen research sources, membership, or
historical results to make a newer implementation appear to reproduce them.
The existing confirmation cohort has already been evaluated; a new final
confirmation claim needs fresh, frozen membership.
The acceptance record and its linked reviews document broader qualification at their recorded source identities. Cite that evidence as historical evidence, separately from checks performed for your change.
Report a problem or propose a change
Open a GitHub issue with the command or smallest example that reproduces the problem, expected and observed behavior, and your Python and package versions. Include a saved result when it helps explain the failure.
For a code or documentation contribution, fork the repository, create a branch
for the change, and open a pull request against main. Describe the problem,
the changed behavior, the commands you ran, and any untested scope. Link the
relevant contract or example. For a new task or a change to the observation or
action contract, describe the proposal in an issue first so the scope and
evaluation can be discussed before a substantial implementation.