2026-05-22 16:17:15 +02:00
# Contributing to Wickra
Thanks for your interest in improving Wickra. This document explains how to
build the project, the standards a change must meet, and how to get it merged.
## License of contributions
2026-06-03 18:49:39 +02:00
Wickra is dual-licensed under the [MIT ](LICENSE-MIT ) and
[Apache-2.0 ](LICENSE-APACHE ) licenses; users may choose either. Unless you
explicitly state otherwise, any contribution you intentionally submit for
inclusion in the work, as defined in the Apache-2.0 license, shall be dual
licensed as above, without any additional terms or conditions.
2026-05-22 16:17:15 +02:00
## Project layout
| Path | Contents |
| --- | --- |
| `crates/wickra-core` | The indicator engine — every indicator lives here. |
| `crates/wickra` | Thin umbrella crate re-exporting `wickra-core` . |
| `crates/wickra-data` | CSV reader, tick aggregator, resampler, Binance feed. |
| `bindings/python` | PyO3 bindings (`wickra` on PyPI). |
| `bindings/node` | napi-rs bindings (`wickra` on npm). |
| `bindings/wasm` | wasm-bindgen bindings (`wickra-wasm` on npm). |
2026-06-09 02:07:03 +02:00
| `bindings/c` | C ABI — `cdylib` + `staticlib` + generated `include/wickra.h` . The hub for C / C++ and any C-capable language. |
2026-06-13 23:34:24 +02:00
| `bindings/csharp` | C# binding over the C ABI (`Wickra` on NuGet) — `[LibraryImport]` P/Invoke generated from `wickra.h` . |
2026-06-09 17:33:37 +02:00
| `bindings/go` | Go binding over the C ABI via cgo (module tag `bindings/go/vX.Y.Z` ) — wrappers generated from `wickra.h` . |
2026-06-09 19:18:40 +02:00
| `bindings/r` | R binding over the C ABI via `.Call` (R package) — C glue + R wrappers generated from `wickra.h` . |
2026-06-09 20:30:29 +02:00
| `bindings/java` | Java binding over the C ABI via the FFM API (Panama, Maven Central) — wrappers generated from `wickra.h` . |
2026-05-22 16:17:15 +02:00
| `examples/` | Runnable examples. |
2026-06-01 23:35:03 +02:00
| `docs/` | Pointer to the documentation site (docs.wickra.org); the docs live in the `wickra-lib/wickra-docs` repo. |
2026-05-22 16:17:15 +02:00
## Building and testing
### Rust
```bash
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo test -p wickra-data --features live-binance
```
2026-05-31 05:30:34 +02:00
The minimum supported Rust version is **1.86** for the workspace crates and
**1.88** for `bindings/node` ; the `msrv` CI job enforces both. These floors are
not chosen freely — they are the lowest versions our dependencies allow
(criterion 0.8.2, the bench dev-dependency, requires 1.86; napi-build 2.3.2
requires 1.88). We keep the MSRV at that dependency-forced floor on purpose so
the library builds for the widest possible audience; please don't raise it
without a dependency that actually requires it.
2026-05-22 16:17:15 +02:00
### Python
```bash
cd bindings/python
python -m maturin build --release --out dist
python -m pip install --force-reinstall --no-deps dist/wickra-*.whl
python -m pytest -q
```
### Node
```bash
cd bindings/node
npm install
npx napi build --platform --release
node --test __tests__/
```
### WASM
```bash
wasm-pack build bindings/wasm --target web --release --features panic-hook
wasm-pack test --node bindings/wasm
```
2026-05-31 05:11:08 +02:00
## Lockfile policy
| Component | Lockfile | Tracked? | Why |
| --- | --- | --- | --- |
| Workspace (Rust) | `Cargo.lock` | **yes** | The workspace ships binaries (examples, fuzz harness) and CI builds, so the dependency graph is pinned for reproducible builds. |
| `bindings/node` | `package-lock.json` | **yes** | Reproducible `npm install` for the native binding. |
| `examples/node` | `package-lock.json` | **yes** | Same — the runnable Node examples link the binding via a `file:` dependency. |
2026-06-01 17:58:31 +02:00
| `bindings/python` | — | n/a (no lockfile) | The published package pins only `numpy>=1.22` at runtime; its native code is pinned through the workspace `Cargo.lock` . The CI/bench dev tooling it installs is hash-locked separately — see the `.github/requirements` row. |
| `.github/requirements` | `*.txt` (hash-pinned) | **yes** | CI/bench Python tooling, locked with `uv pip compile --generate-hashes` (OpenSSF Scorecard PinnedDependencies). `ci-dev` is split per Python version — `ci-dev-py39.txt` and `ci-dev-py3.txt` — because numpy ships no single release with wheels for both cp39 and cp313; `bench.txt` covers the single-version bench job. |
2026-05-31 05:11:08 +02:00
| `fuzz` | `fuzz/Cargo.lock` | **no** (ignored) | `fuzz/` is a detached crate; `cargo-fuzz init` generates `fuzz/.gitignore` which ignores its `Cargo.lock` . The fuzz smoke job resolves dependencies fresh, so the lock is not needed for reproducibility here. |
| `site` (marketing) | `package-lock.json` | **no** (ghost-ignored) | The VitePress site is a local-only project excluded via `.git/info/exclude` ; its lockfile stays local. |
When adding a new committed Node package, commit its `package-lock.json` too and
remove any matching ignore rule. Do **not** add a top-level `package-lock.json` —
the repository root is not an npm package.
2026-06-01 17:58:31 +02:00
To refresh every committed lockfile in the workspace — `Cargo.lock` ,
`fuzz/Cargo.lock` , the Node binding lock, and the hash-pinned Python
requirements — run `./scripts/update-lockfiles.sh` . It uses `uv` for the Python
locks (and bootstraps it on Linux/macOS if absent) so each target Python
version's hashed transitive closure can be regenerated without that interpreter
installed. Dependabot also keeps the `.github/requirements` pins current.
2026-05-22 16:17:15 +02:00
## Standards for a change
- **Formatting & lints.** `cargo fmt` must leave the tree unchanged and
`cargo clippy ... -D warnings` must be clean. CI gates both.
- **Tests.** New behaviour needs tests; bug fixes need a regression test.
- **Indicator correctness.** A new or changed indicator must have a
reference-value test against a known-good source (TA-Lib, pandas-ta, or a
hand-computed value) and a `reset` test.
- **Streaming parity.** An indicator's `batch` output must equal the sequence
of `update` calls.
- **Bindings.** A change to a public indicator API must be mirrored across the
2026-06-13 23:34:24 +02:00
Python, Node.js, and WASM bindings, including their type stubs / `.d.ts` . The C ABI
2026-06-09 02:14:28 +02:00
(`bindings/c` ) is generated from the core, so regenerate it from the core and
2026-06-09 14:32:05 +02:00
commit `src/lib.rs` + `include/wickra.h` . The C# binding (`bindings/csharp` ) is
generated from `wickra.h` , so regenerate and commit its `Generated/*.g.cs` too.
2026-06-09 17:33:37 +02:00
The Go binding (`bindings/go` ) is likewise generated from `wickra.h` , so
2026-06-09 19:18:40 +02:00
regenerate and commit `indicators_gen.go` (`gofmt` -clean). The R binding
(`bindings/r` ) is generated from `wickra.h` too, so regenerate and commit
2026-06-09 20:30:29 +02:00
`src/wickra.c` + `R/indicators.R` . The Java binding (`bindings/java` ) is
generated from `wickra.h` as well, so regenerate and commit its
`src/main/java/org/wickra/*.java` .
2026-05-23 22:48:48 +02:00
- **Docs.** Update the relevant page on the
2026-05-31 21:48:24 +02:00
[documentation site ](https://docs.wickra.org ) and the
`README.md` when behaviour or the public API changes. The docs live in
a separate git repository: `https://github.com/wickra-lib/wickra-docs` .
2026-05-22 16:17:15 +02:00
- **Changelog.** Add an entry under `## [Unreleased]` in `CHANGELOG.md` .
## Commit and pull-request workflow
1. Branch off `main` .
2. Keep commits focused — one logical change per commit, with an imperative
subject line and a body explaining *why* .
3. Open a pull request against `main` and fill in the template.
4. CI must be green before review.
## Reporting bugs and proposing features
Use the issue templates under
[`.github/ISSUE_TEMPLATE` ](.github/ISSUE_TEMPLATE ). For security-sensitive
reports, follow [`SECURITY.md` ](SECURITY.md ) instead of opening a public issue.
2026-06-03 22:16:03 +02:00
## Developer Certificate of Origin (DCO)
All contributions to Wickra are made under the [Developer Certificate of
Origin (DCO) 1.1 ](DCO ). By signing off on your commits you certify that you
wrote the patch, or otherwise have the right to submit it under the project's
`MIT OR Apache-2.0` license.
Sign off every commit by adding a `Signed-off-by` trailer with your real name
and email — Git adds it automatically with the `-s` flag:
```bash
git commit -s -m "your message"
```
This produces a trailer of the form:
```
Signed-off-by: Your Name <you@example.com>
```
The name and email must match the commit author. Commits without a valid
sign-off line cannot be merged. To sign off a commit you already made, amend it
with `git commit -s --amend` , or sign off a range with an interactive rebase.
## Governance
Wickra's decision-making and maintainership are described in
[`GOVERNANCE.md` ](GOVERNANCE.md ); the current maintainers are listed in
[`MAINTAINERS.md` ](MAINTAINERS.md ).