Skip to content

Contribute to binoc

Goal. Go from a fresh clone to a merged PR.

Prerequisites. - Rust - just (brew install just on macOS) - uv

If you only want to use binoc, you don't need any of this — see Diff two snapshots instead.

Architectural ground rules

Read AGENTS.md first. It's the architectural contract for both human and AI contributors. Headlines:

  • The controller is type-ignorant. Never add format knowledge to binoc-core. See Architecture overview.
  • The standard library is a plugin pack. It has no special status relative to third-party plugins.
  • The library is the product; the CLI is porcelain. Design APIs for embedding first.
  • Greenfield. Note breaking changes, but don't spend effort on backwards compatibility.

Longer form: the architecture overview narrates the system; the ADR set is the canonical record of every design decision with rejected alternatives.

First-time setup

git clone https://github.com/harvard-lil/binoc
cd binoc
just build       # Rust workspace + Python bindings (debug)
just test        # Full suite: Rust + Python

For a local CLI in your path:

uv venv
uv pip install -e ./binoc-python
source .venv/bin/activate

Or run the dev CLI with every local plugin wired up, no global install:

just binoc diff path/to/snapshot-a path/to/snapshot-b

See the existing tutorial for a fuller walkthrough that regularly re-verifies against the current code via Showboat.

The everyday loop

# 1. Make your change

just fmt           # auto-format Rust + Python
just check         # mirror CI (clippy, rustfmt --check, ruff)
just test          # Rust + Python test suites

For focused iteration: cargo build or cargo test -p binoc-core (etc.) skip the Python crate and are much faster than just test.

Where things live

You want to… Start in…
Add a new test vector test-vectors/ — create snapshot-a/, snapshot-b/, manifest.toml. See Test vectors explanation.
Add a stdlib comparator or transformer binoc-stdlib/src/comparators/ or .../transformers/. For third-party plugins, see Write a Python comparator / Write a Rust comparator.
Change the IR binoc-sdk/src/ir.rs (wire types) and binoc-core/src/ir.rs (in-memory additions). IR changes are high-leverage; read IR and changesets first.
Fix the controller / dispatch logic binoc-core/src/controller.rs. See Dispatch model.
Fix the CLI binoc-cli/src/lib.rs (the library); binoc-cli/src/main.rs is a thin wrapper around binoc_cli::run().
Add a Python API surface binoc-python/src/lib.rs (PyO3) and binoc-python/python/binoc/__init__.py.
Tune default significance binoc-stdlib/src/renderers/markdown.rsdefault_significance. See Significance classification.

Test vectors are the cheap contribution

Adding a new test vector is the lowest-friction way to contribute a meaningful improvement. You get:

  1. A named fixture that documents a capability (or a bug) in test-vectors/.
  2. Coverage in just test via the shared harness.
  3. Reference material that appears in the documentation and tutorial.

The convention: name vectors for what they test (csv-column-reorder), not how (test-comparator-csv-3). See Test vectors.

Documentation

Docs live in docs/ and are published via MkDocs. See Write and maintain docs for the full guide. Quick reference:

just docs          # regenerate all generated inputs
just docs-serve    # live preview at 127.0.0.1:8000
just docs-build    # strict build (CI mirror); fails on broken links or orphan pages

If you change behavior the tutorial demonstrates, regenerate it with just docs-tutorial (Showboat).

PR conventions

  • Small, focused PRs. Easier to review, easier to roll back.
  • Tests for new behavior. A test vector often suffices.
  • Update docs when you change user-visible behavior.
  • Note breaking changes in the PR description, but don't spend effort on backwards compatibility — see AGENTS.md.
  • ADR any design decision whose rejected alternatives are non-obvious.

Where to go next