#mutation-testing #static-analysis #lsp

bin+lib ripr

Find Rust test-oracle gaps before mutation testing with static RIPR evidence

6 releases (breaking)

Uses new Rust 2024

new 0.5.0 May 10, 2026
0.4.0 May 7, 2026
0.3.1 May 7, 2026
0.2.0 May 1, 2026
0.1.0 May 1, 2026

#258 in Testing

Download history 2160/week @ 2026-05-07

2,183 downloads per month

MIT/Apache

3MB
73K SLoC

ripr

ripr helps Rust developers and coding agents find test-oracle gaps before mutation testing.

It answers a draft-time testing question:

For the behavior changed in this diff, do the current tests appear to contain
a discriminator that would notice if that behavior were wrong?

ripr is alpha software. The current release is a syntax-first scanner that is useful for early feedback, not a proof system.

This is the product repository for ripr. The 0.5.x line keeps the analyzer, editor, CI, and agent loops aligned around static evidence for targeted tests.

Mission

ripr helps Rust developers and coding agents write tests that actually notice changed behavior.

It performs static RIPR exposure analysis over changed Rust code, creates mutation-shaped probes, and reports whether existing tests appear to contain the discriminators needed to expose those changes.

It is a fast draft-mode companion to real mutation testing: static guidance while the pull request is moving, real mutation confirmation when the change is ready.

Vision

The vision for ripr is to become the live test-adequacy layer between coverage and mutation testing for Rust/Cargo workspaces.

Coverage tells developers what executed. Mutation testing tells developers what survived. ripr tells developers, reviewers, and agents what changed behavior appears to lack a meaningful oracle before the expensive mutation run begins.

The end state is an LSP-native sidecar that watches changed code, identifies missing discriminators, explains the evidence path, emits agent-ready test intent, and calibrates itself against real mutation outcomes.

Category

ripr defines its category as:

Static Mutation Exposure Analysis

More specifically:

Static oracle-gap analysis for diff-derived mutation probes.

The tool is not trying to be a coverage dashboard, a full mutation engine, a proof system, a second rust-analyzer, or a generic LLM test generator. Its job is to shorten the path from "this behavior changed" to "this is the exact test oracle that should notice."

What ripr Does

ripr reads changed Rust code, creates mutation-shaped probes, and estimates whether related tests appear to reach, infect, propagate, observe, and discriminate the changed behavior.

It looks for missing or weak test oracles such as:

  • boundary changes without boundary-value assertions
  • error-path changes checked only with is_err()
  • return-value changes checked only with smoke assertions
  • field construction changes without field, object, or snapshot assertions
  • side effects without mock, event, state, persistence, or metric oracles

What ripr Does Not Do

ripr does not run mutants.

It does not report killed or survived, prove test adequacy, replace coverage, or replace real mutation testing. Use a real mutation runner, such as cargo-mutants, when the change is ready for confirmation.

Where It Fits

coverage:
  did this code execute?

ripr:
  does changed behavior appear exposed to a meaningful oracle?

mutation testing:
  did tests fail when a concrete mutant was run?

The goal is fast, honest oracle-gap feedback while code is still changing.

Ecosystem Positioning

Existing layer What it answers Gap
cargo-llvm-cov Did code execute? Not oracle-aware
selective retest tools Which tests are impacted? Not assertion-aware
cargo-mutants Did real mutants survive? Too expensive for live draft feedback
rust-analyzer What does Rust code mean in the editor? Does not rank mutation exposure
ripr Does changed behavior appear exposed to a meaningful oracle? New middle layer

Install

Install from crates.io:

cargo install ripr

Links:

For local development from this repository:

cargo install --path crates/ripr

ripr targets Rust 2024 and requires Rust 1.95 or newer.

Quick Start

# Check local tooling and workspace shape
ripr doctor

# Analyze the current Git diff against origin/main
ripr check --base origin/main

# Analyze an explicit unified diff
ripr check --diff example.diff

# Emit stable JSON for tools and agents
ripr check --diff example.diff --json

# Emit GitHub Actions annotations
ripr check --diff example.diff --format github

# Explain one finding
ripr explain --diff example.diff probe:src_lib.rs:88:predicate

# Emit an agent-ready context packet
ripr context --diff example.diff --at probe:src_lib.rs:88:predicate --json

# Start the experimental LSP sidecar
ripr lsp

Example Finding

WARNING src/pricing.rs:88

Static exposure: weakly_exposed (predicate, control)

Changed behavior:
  after:  if amount >= discount_threshold {

RIPR:
  Reach:        yes
  Infect:      weak
  Propagate:   yes
  Observe:     yes
  Discriminate: weak

Gap:
  - No detected boundary input for the changed predicate
  - No strong discriminator was detected

Recommended next step:
  Add below, equal, and above threshold tests with exact assertions.

Output Formats

Human output is optimized for local use.

JSON output is versioned and intended for editor integrations, CI, and coding agents:

{
  "schema_version": "0.1",
  "tool": "ripr",
  "mode": "draft",
  "base": "origin/main",
  "findings": []
}

GitHub output emits workflow annotations.

Classifications

Classification Meaning
exposed Static evidence suggests a complete RIPR path to a strong oracle.
weakly_exposed A path exists, but infection or discrimination appears weak.
reachable_unrevealed Related tests appear reachable, but no meaningful oracle was found.
no_static_path No static test path was found for the changed owner.
infection_unknown Reachability exists, but input or fixture evidence is opaque.
propagation_unknown The changed behavior crosses an opaque propagation boundary.
static_unknown Syntax-first analysis cannot make a credible judgment.

Current Scope

The current alpha line is intentionally narrow:

  • one published package: ripr
  • one CLI binary: ripr
  • one shared analysis engine
  • syntax-first unified diff analysis
  • basic Rust function, test, and assertion indexing
  • human, JSON, and GitHub outputs
  • experimental LSP sidecar

The package is not split into ripr-core, ripr-cli, or ripr-lsp. Public crate boundaries can be added later if external consumers need them.

Current Capability Snapshot

ripr is currently strongest as a fast, syntax-backed draft signal with a defaults-first operator loop for finding one weak seam, adding one focused test, and comparing before/after evidence.

Capability Current state Next checkpoint
Distribution 0.5.0 is the prepared release line for the Rust crate, VS Code/Open VSX extension, GitHub Release server assets, generated CI workflow artifacts, and Rust 1.95 MSRV. 0.4.0 remains the last publicly verified release until the publish checklist completes. Publish 0.5.0, then refresh public install and marketplace verification receipts.
Diff analysis Syntax-backed changed-line probes with owner symbols, parser-backed probe facts, explicit stop reasons for unknowns, probe-relative oracle strength, and local flow sink facts. Maintenance; no active analyzer-refactor lane.
Test discovery Parser-backed test and assertion facts with exact, broad, relational, snapshot, mock, smoke, and unknown oracle kinds. Maintenance; no active analyzer-refactor lane.
Output Human, JSON, context, GitHub/SARIF, repo seam, pilot, outcome, and badge formats include evidence-first stop reasons and advisory next actions. Output contract maintenance.
LSP Experimental tower-lsp-server sidecar with saved-workspace seam diagnostics, hovers, targeted context actions, refresh status, and related-test actions. Editor contract maintenance.
Agent context Context packets and agent seam packets include targeted-test briefs with missing values and assertion shape. Agent-context v2 when there is a concrete external contract.
Calibration ripr calibrate cargo-mutants imports supplied runtime mutation data and joins it to repo seam evidence for advisory static/runtime calibration; fixtures/EXAMPLE_CORPUS.md links the checked boundary-gap sample into the operator loop, and fixtures/boundary_gap/calibration/runtime-fixtures-v1/ pins the main static/runtime agreement buckets. Maintenance; runtime data stays optional and supplied.

Development

cargo fmt --check
cargo check --workspace --all-targets
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo doc --workspace --no-deps
cargo package -p ripr --list
cargo publish -p ripr --dry-run

Useful sample commands:

cargo run -p ripr -- check --diff crates/ripr/examples/sample/example.diff
cargo run -p ripr -- check --diff crates/ripr/examples/sample/example.diff --json

Dependencies

~14–29MB
~319K SLoC