chelae 0.2.1

A toolkit for trimming and filtering FASTQ reads.
Documentation
# Contributing to chelae

This document is for developers working on `chelae` itself. End-user
documentation lives in [README.md](README.md).

## Pre-push checks

Before pushing, run the full verification suite:

```console
bash ci/check.sh
```

This runs the cargo aliases defined in `.cargo/config.toml`, which CI runs as
well: `cargo ci-fmt` (a formatting check; `cargo fmt --all` fixes it),
`cargo ci-lint` (clippy with `-D warnings`) and `cargo ci-test`, all `--locked`
where it applies.

The pinned toolchain (`rust-toolchain.toml`) is what CI uses; the minimum
supported version is the `rust-version` in `Cargo.toml`. Clippy's
`incompatible_msrv` lint flags standard-library APIs newer than that minimum.

## Building from source

Clone the repository and build in release mode. If you don't have Rust yet, install it with [rustup](https://rustup.rs/); `rust-toolchain.toml` pins the version CI uses, and rustup fetches it on the first build.

```console
git clone https://github.com/fulcrumgenomics/chelae.git
cd chelae
cargo build --release
./target/release/chelae --help
```

## Build targeting and portability

`cargo build --release` produces a portable build for the target's baseline CPU, since `.cargo/config.toml` sets no `target-cpu`. For local profiling, tune it to your machine with `RUSTFLAGS="-C target-cpu=native" cargo build --release`.

x86_64 release binaries are built with `cargo multivers --profile dist` as a single launcher that embeds three CPU-specific builds and picks the best match at startup:

- `x86-64`: SSE2 baseline, runs on any 64-bit x86 CPU (2003+)
- `x86-64-v2`: SSE4.2 + POPCNT (2008+); captures nearly all of the speed-up over the baseline
- `x86-64-v4`: AVX-512F/BW/CD/DQ/VL for Ice Lake / Sapphire Rapids / Granite Rapids / Zen 4+

The launcher is ~4 MB and adds ~0.2 s of startup for decompression + `memfd_create` + `exec`. v3 is skipped on purpose: on chelae's workload v2 and v3 are within measurement noise, and v4 adds what little AVX-512 gives (~1% on our benchmarks).

aarch64 release binaries (Apple Silicon, AWS Graviton, GCP Axion, Azure Cobalt) are a single build (`cargo build --profile dist`) for the generic ARMv8-A / NEON baseline. Neoverse-specific tuning gained only ~1-2% over generic in our benchmarks, with a near-zero penalty on other cores, so multivers isn't worth the complexity there.

## Code organization

The project follows conventions documented in [`CLAUDE.md`](CLAUDE.md) —
section ordering within command modules, impl-block collocation, and
callers-before-callees inside an impl. Please read `CLAUDE.md` before making
structural changes.

## Updating the usage docs

[`docs/usage.md`](docs/usage.md) has hand-curated **Options** tables that summarize every visible `chelae trim` and `chelae detect` option. When adding, removing, or renaming an option (or materially changing its meaning or default), update those tables so the docs stay in step with the CLI. The `--help` output remains the authoritative reference; the tables are short-form pointers to it.

## Changelog

`CHANGELOG.md` follows the [Keep a Changelog](https://keepachangelog.com/)
format and is promoted on release by `cargo-release`. As you make user-visible
changes, add a bullet under the `[Unreleased]` section heading using the
appropriate subsection (`Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`,
or `Security`).

## Releasing a new version

Releases are cut from a clean, up-to-date `main`. Nothing publishes automatically: `cargo release` bumps, tags and pushes, and the crates.io publish and GitHub release are separate manual steps.

### Pre-requisites

- [`cargo-release`][cargo-release-link]: `cargo install cargo-release`
- A crates.io API token with publish rights on `chelae` (`cargo login`)
- The GitHub CLI, `gh`, authenticated for this repository

### 1. Bump, tag and push

Check the plan first; `cargo release` is a dry run unless given `--execute`:

```console
cargo release [major|minor|patch|release|rc] --no-publish
```

Then run it for real:

```console
cargo release [major|minor|patch|release|rc] --no-publish --execute
```

This bumps the version, promotes the CHANGELOG's `[Unreleased]` section to the new version, commits `release: vX.Y.Z`, tags `vX.Y.Z` and pushes both. `release.toml` sets the tag format and the CHANGELOG edits and has `publish = false`, but pass `--no-publish` anyway: without it `cargo release` still prints a publishing step, which is confusing. See the [`cargo-release` reference documentation][cargo-release-docs-link] for more.

### 2. Publish to crates.io

From the tag, check the package and then publish it. A published version can't be replaced, only yanked, so read the dry run's file list first:

```console
git checkout vX.Y.Z
cargo publish --locked --dry-run
cargo publish --locked
```

### 3. Create the GitHub release

Use the version's CHANGELOG section as the notes, with each wrapped paragraph and bullet joined onto one line, since GitHub renders single newlines as line breaks:

```console
gh release create vX.Y.Z --verify-tag --title "vX.Y.Z" --notes-file release-notes.md
```

bioconda's autobump bot picks up the new release and opens the recipe update on its own.

### Semantic versioning

`chelae` follows [Semantic Versioning](https://semver.org/):

- **MAJOR** when you make incompatible API changes,
- **MINOR** when you add functionality in a backwards-compatible manner,
- **PATCH** when you make backwards-compatible bug fixes.

## Benchmark pipeline

The benchmark pipeline that produces the numbers in `README.md` and
`benchmark-pipeline/RESULTS.md` is documented separately in
[`benchmark-pipeline/README.md`](benchmark-pipeline/README.md). That's where
to look if you're modifying tool render scripts, adding a new tool to the
comparison, changing the sample matrix, or re-running the benchmark suite.

[cargo-release-link]:      https://github.com/crate-ci/cargo-release
[cargo-release-docs-link]: https://github.com/crate-ci/cargo-release/blob/master/docs/reference.md