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:
Or run the dev CLI with every local plugin wired up, no global install:
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.rs — default_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:
- A named fixture that documents a capability (or a bug) in
test-vectors/. - Coverage in
just testvia the shared harness. - 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¶
- Architecture overview — build the mental model before making a structural change.
- Test vectors — the easy-first contribution path.
- Cut a release — once your change is merged and deserves a version bump.