Skip to content

fix: resolve 10 missed cargo-mutants mutations#5

Merged
EffortlessSteven merged 11 commits into
mainfrom
fix/mutants-missed
Feb 20, 2026
Merged

fix: resolve 10 missed cargo-mutants mutations#5
EffortlessSteven merged 11 commits into
mainfrom
fix/mutants-missed

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

Summary

  • Pass --all-features to cargo mutants in xtask so feature-gated adapter code (aws-lc-rs) is tested (fixes 3 mutations)
  • Add exclude_re in mutants.toml for unkillable no-op mutations: new_cache, cache_len, cache_clear (fixes 7 mutations)
  • Strengthen debug_includes_cache_size test to assert exact numeric values

Test plan

  • cargo xtask fmt — clean
  • cargo xtask clippy — clean
  • cargo test -p uselesskey-core debug_includes_cache_size — passes
  • CI cargo xtask mutants should report 0 MISSED

Pass --all-features to cargo mutants so feature-gated adapter code
is tested. Exclude unkillable no-op mutations (new_cache, cache_len,
cache_clear). Strengthen debug_includes_cache_size to assert exact values.
Copilot AI review requested due to automatic review settings February 19, 2026 00:45
@coderabbitai

coderabbitai Bot commented Feb 19, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added token generation and PGP key support with comprehensive test coverage.
    • Introduced cross-backend cryptographic interoperability testing.
  • Tests

    • Added behavior-driven development tests for tokens and PGP.
    • Added property-based tests across ECDSA, Ed25519, HMAC, and PGP crates.
    • Added negative-path TLS handshake and fuzz tests.
  • Documentation

    • Added issue templates, pull request template, and code of conduct.
    • Added support guide and community funding configuration.
  • Chores

    • Enabled Dependabot for automated dependency updates.
    • Added mutation testing configuration.

Walkthrough

This PR establishes comprehensive testing infrastructure, governance, and CI tooling for the project. It adds configuration files (cargo-mutants, Dependabot), governance documentation (CODE_OF_CONDUCT, issue templates), a new interoperability test crate, property-based tests across cryptographic modules, behavioral test features for tokens and PGP, and enhancements to build orchestration with coverage tracking.

Changes

Cohort / File(s) Summary
Configuration & Governance
.cargo/mutants.toml, .github/FUNDING.yml, .github/ISSUE_TEMPLATE/bug_report.md, .github/ISSUE_TEMPLATE/feature_request.md, .github/PULL_REQUEST_TEMPLATE.md, .github/dependabot.yml, CODE_OF_CONDUCT.md, SUPPORT.md, mutants.toml
Adds mutation testing configuration with excluded paths/patterns; GitHub governance files (funding declaration, issue/PR templates); Dependabot for cargo and GitHub Actions; contributor code of conduct; and support documentation. Removes legacy mutants configuration from root.
Documentation
README.md
Adds CI, crates.io, and license badges to README header.
Workspace & Manifest
Cargo.toml, crates/uselesskey-bdd/Cargo.toml, crates/uselesskey-hmac/Cargo.toml, crates/uselesskey-pgp/Cargo.toml, crates/uselesskey-token/Cargo.toml, fuzz/Cargo.toml
Registers uselesskey-interop-tests workspace member; expands BDD crate features (adds uk-token, uk-pgp) and dev-dependencies; adds proptest to multiple crates' dev-dependencies; updates fuzz targets with ECDSA and token features.
BDD Test Suite
crates/uselesskey-bdd/features/pgp.feature, crates/uselesskey-bdd/features/token.feature, crates/uselesskey-bdd/tests/bdd.rs
Introduces feature files for deterministic/random PGP and token fixture generation with comprehensive scenarios; expands BDD test world with feature-gated storage (token and PGP fields) and step definitions for token/PGP operations, assertions, and error handling.
Core & Signature Algorithm Unit Tests
crates/uselesskey-core/src/factory_tests.rs, crates/uselesskey-core/src/negative/der.rs, crates/uselesskey-ecdsa/tests/ecdsa_prop.rs, crates/uselesskey-ecdsa/tests/testutil.rs, crates/uselesskey-ed25519/tests/ed25519_prop.rs, crates/uselesskey-ed25519/tests/testutil.rs, crates/uselesskey-hmac/tests/hmac_prop.rs, crates/uselesskey-pgp/tests/pgp_prop.rs, crates/uselesskey-pgp/tests/testutil.rs, crates/uselesskey-token/src/token.rs, crates/uselesskey-token/tests/testutil.rs, crates/uselesskey-token/tests/token_prop.rs
Adds property-based tests (proptest) across ECDSA, Ed25519, HMAC, and PGP modules validating deterministic stability, parseability, format correctness, and feature-gated behaviors (e.g., kid determinism); introduces testutil helpers providing lazy-initialized deterministic factories per crate.
Interoperability Tests
crates/uselesskey-interop-tests/Cargo.toml, crates/uselesskey-interop-tests/src/lib.rs, crates/uselesskey-interop-tests/tests/interop.rs
Creates new crate for cross-backend interoperability; configures dev-dependencies for ring, p256, ed25519-dalek, rsa; implements tests verifying signing with one backend (p256, ed25519-dalek, rustcrypto rsa) and verification with ring; includes ASN.1 SPKI parsing helpers and tamper-evidence validation.
Additional Cryptographic Tests
crates/uselesskey-jsonwebtoken/tests/jwt_comprehensive.rs, crates/uselesskey-rustls/tests/negative.rs, fuzz/fuzz_targets/ecdsa_pkcs8_pem_parse.rs, fuzz/fuzz_targets/token_format.rs
Adds JWT mismatched-key rejection test; introduces TLS negative-path tests (expired certificates, unknown CA) with handshake helpers and provider initialization; adds fuzz targets for ECDSA PKCS#8 PEM corruption and token format variants.
Build & CI Tooling
xtask/src/main.rs, xtask/src/receipt.rs
Refactors xtask mutants flow into run_mutants(crates) function with per-crate execution; adds feature matrix combinations for testing; implements LCOV coverage parsing with percentage computation; extends Receipt struct with coverage_percent field and setter method for CI pipeline integration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hops through config, governance, and test—
BDD features bloom, tokens and keys manifest!
Cross-backend signs dance with verification's grace,
Coverage metrics gleam in the CI embrace. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: resolve 10 missed cargo-mutants mutations' directly describes the main change—resolving mutations that were not being killed by cargo-mutants. It is concise, specific, and clearly indicates the primary objective of the PR.
Description check ✅ Passed The PR description is directly related to the changeset, providing a summary of three key changes (passing --all-features, adding exclude_re entries, strengthening tests) and a test plan. It accurately describes aspects of the modifications throughout the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/mutants-missed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @EffortlessSteven, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request aims to improve the accuracy and coverage of mutation testing within the project. It addresses 10 previously missed mutations by correctly configuring the cargo-mutants tool to test all features and by excluding mutations that are semantically no-ops and unkillable. Additionally, a related test case was enhanced to provide more precise assertions.

Highlights

  • Mutation Testing Configuration: Configured cargo mutants in xtask to pass --all-features, ensuring feature-gated code (like aws-lc-rs) is included in mutation tests, resolving 3 previously missed mutations.
  • Mutation Exclusion: Added regular expressions to mutants.toml to exclude 7 specific unkillable no-op mutations (e.g., new_cache, cache_len, cache_clear) from cargo-mutants reports.
  • Test Improvement: Strengthened the debug_includes_cache_size test in uselesskey-core to assert exact numeric values for cache sizes (0 and 1) at different points, improving test precision.
Changelog
  • crates/uselesskey-core/src/factory_tests.rs
    • Updated the debug_includes_cache_size test to assert the exact cache size (0 and 1) at different stages of factory initialization.
  • mutants.toml
    • Added exclude_re entries to ignore specific mutations related to new_cache, cache_len, and cache_clear that are considered unkillable no-ops.
  • xtask/src/main.rs
    • Modified the cargo mutants command to include the --all-features flag, ensuring comprehensive mutation testing across all feature sets.
Activity
  • The author confirmed cargo xtask fmt runs clean.
  • The author confirmed cargo xtask clippy runs clean.
  • The author confirmed cargo test -p uselesskey-core debug_includes_cache_size passes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request resolves several missed mutations from cargo-mutants. The changes include passing --all-features to the mutants command in xtask, excluding known unkillable mutations in mutants.toml with clear justifications, and strengthening the debug_includes_cache_size test to be more specific. All changes are well-implemented and directly address the goal of improving mutation testing results. The code quality is excellent, and I have no suggestions for improvement.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens mutation testing coverage by ensuring feature-gated code is exercised during cargo mutants runs and by excluding specific unkillable/no-op mutations, plus it strengthens an existing debug-output test around cache sizing.

Changes:

  • Update xtask mutants to run cargo mutants --all-features so feature-gated code is included in mutation testing.
  • Add exclude_re entries in mutants.toml to ignore specific mutations deemed unkillable/no-op (new_cache, cache_len, cache_clear).
  • Strengthen debug_includes_cache_size test expectations for cache size values.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
xtask/src/main.rs Runs mutation testing with --all-features via xtask.
mutants.toml Excludes specific mutation patterns via exclude_re.
crates/uselesskey-core/src/factory_tests.rs Tightens debug cache-size assertions in tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +103 to +108
let dbg = format!("{:?}", fx);
assert!(dbg.contains("cache_size: 0"), "empty factory: {dbg}");

let _ = fx.get_or_init("domain:test", "label", b"spec", "good", |_rng| 7u8);
let dbg = format!("{:?}", fx);
assert!(dbg.contains("cache_size"), "debug output was: {dbg}");
assert!(dbg.contains("cache_size: 1"), "after insert: {dbg}");

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion dbg.contains("cache_size: 1") can produce false positives (e.g., it would also match cache_size: 10). If the goal is to assert the exact numeric value, consider extracting/parsing the cache_size number from the debug string and comparing it as an integer, or matching a delimiter like cache_size: 1 } / cache_size: 1, to avoid substring matches.

Copilot uses AI. Check for mistakes.
Comment thread mutants.toml Outdated
Comment on lines +15 to +20
# DashMap::new() == Default::default(); semantic no-op that cannot be killed
"replace new_cache",
# cfg(not(feature = "std")) variants are dead code under default (and all) features.
# std variants are trivial single-line delegations (DashMap::len / DashMap::clear).
"replace cache_len",
"replace cache_clear",

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation inside exclude_re is inconsistent with the earlier exclude_globs list (2-space indent vs 4-space). For readability/consistency within this config file, consider using the same indentation style for array entries and comments throughout.

Suggested change
# DashMap::new() == Default::default(); semantic no-op that cannot be killed
"replace new_cache",
# cfg(not(feature = "std")) variants are dead code under default (and all) features.
# std variants are trivial single-line delegations (DashMap::len / DashMap::clear).
"replace cache_len",
"replace cache_clear",
# DashMap::new() == Default::default(); semantic no-op that cannot be killed
"replace new_cache",
# cfg(not(feature = "std")) variants are dead code under default (and all) features.
# std variants are trivial single-line delegations (DashMap::len / DashMap::clear).
"replace cache_len",
"replace cache_clear",

Copilot uses AI. Check for mistakes.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f53beb43a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread xtask/src/main.rs Outdated

match status {
Ok(s) if s.success() => run(Command::new("cargo").args(["mutants"])),
Ok(s) if s.success() => run(Command::new("cargo").args(["mutants", "--all-features"])),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid forcing native aws-lc feature in mutants runs

Running cargo mutants --all-features here makes xtask mutants enable every crate feature in the workspace, including uselesskey-aws-lc-rs/native; that feature is explicitly documented as requiring NASM on Windows (crates/uselesskey-aws-lc-rs/Cargo.toml), so this change turns a previously runnable local command into a platform-dependent failure for contributors who don't have that toolchain installed.

Useful? React with 👍 / 👎.

…xpansion

- Add 27 PGP BDD scenarios covering determinism, key formats, parsing,
  user IDs, fingerprints, negative fixtures, corruption, and tempfiles
- Add 22 Token BDD scenarios covering API keys, bearer tokens, OAuth
  access tokens, determinism, format validation, and variant isolation
- Add mutant-kill tests: derived_offset_returns_nonzero (der.rs),
  random_base62_uses_full_alphabet (token.rs)
- Move mutants.toml to .cargo/mutants.toml
- Expand feature matrix with key+format combinations (rsa+jwk, etc.)
- Fix BDD Cargo.toml: uk-all now activates all individual feature flags
- ECDSA: 6 properties (32 cases) covering deterministic stability for
  ES256/ES384, parseability via p256/p384, and kid determinism
- Ed25519: 4 properties (64 cases) covering deterministic stability,
  parseability via ed25519-dalek, and kid determinism
- HMAC: 5 properties (64 cases) covering deterministic stability,
  secret length matching spec (32/48/64), and label isolation
- Add proptest dev-dep to uselesskey-hmac
- Token: 5 properties (64 cases) covering API key prefix/length,
  bearer base64url validity, OAuth 3-segment format, spec isolation,
  and deterministic stability
- PGP: 4 properties (16 cases, Ed25519 only) covering armor
  parseability, binary parseability, fingerprint stability, and
  fingerprint non-emptiness
- Add proptest dev-dep to both crates
- rustls: expired cert and unknown CA TLS handshake rejection tests
- jsonwebtoken: mismatched public key rejects JWT signature
New test-only crate proving keys work across crypto backends:
- ECDSA P-256: p256 sign -> ring verify
- Ed25519: ed25519-dalek sign -> ring verify
- RSA: rsa crate sign -> ring verify
Each with tamper-rejection counter-tests (6 tests total).
- ecdsa_pkcs8_pem_parse: corrupt good ECDSA P-256 PEM, parse with p256
- token_format: arbitrary seeds, assert format invariants for all 3 specs
- Add parse_lcov_coverage() to extract line coverage from lcov.info
- Print coverage percentage after cargo-llvm-cov runs
- Add coverage_percent field to receipt.json (omitted when not set)
- 6 new unit tests for coverage parsing and receipt serialization
Refactor `mutants()` into `run_mutants(crates)` which iterates over
publishable crates using `--manifest-path` instead of running
workspace-wide.  `--all-features` is now only passed in CI or when
`XTASK_MUTANTS_ALL_FEATURES` is set, avoiding the NASM requirement on
local Windows dev machines.  PR mode further scopes to only the
impacted publishable crates.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/dependabot.yml:
- Around line 8-11: Add an explicit open-pull-requests-limit to the
github-actions dependabot block: update the block that currently contains
package-ecosystem: "github-actions", directory: "/", schedule: interval:
"weekly" to include open-pull-requests-limit (e.g., set to 5) so the
github-actions updates are capped similarly to the cargo block and prevent
unbounded PR creation.

In @.github/ISSUE_TEMPLATE/bug_report.md:
- Line 28: Update the example Rust version in the bug report template so it
matches the project's MSRV: replace the string "Rust Version [e.g. 1.75]" with
an updated example such as "Rust Version [e.g. 1.88]" and add a short note
reminding reporters to use the project's MSRV (1.88) when reproducing issues;
ensure the exact template text "Rust Version [e.g. 1.75]" is updated wherever it
appears.

In @.github/PULL_REQUEST_TEMPLATE.md:
- Around line 20-23: Add a "Mutation Tests" checkbox to the PR checklist in the
template so contributors remember to run the project's mutation test step;
specifically, update the checklist section that currently lists "Unit Tests",
"BDD Tests (`cargo xtask bdd`)", "Property Tests", and "Manual Integration
Tests" by inserting a new item like "Mutation Tests (`cargo xtask mutants`)"
adjacent to those entries (ensure the wording matches the CLI `cargo xtask
mutants` so it's discoverable).

In `@Cargo.toml`:
- Line 20: Centralize p256, sha2, and signature into the root
[workspace.dependencies] and switch the per-crate declarations to reference the
workspace to avoid version divergence: add p256 = "0.13.2" (reconciling to the
version used by uselesskey-bdd), sha2 = "0.10", and signature = "2" under
[workspace.dependencies], then in each crate manifest that currently declares
them (e.g., uselesskey-ecdsa, uselesskey-rustcrypto, fuzz, tests, interop-tests,
etc.) replace the inline version specs with p256 = { workspace = true }, sha2 =
{ workspace = true }, signature = { workspace = true } so all crates use the
single workspace-managed versions.

In `@CODE_OF_CONDUCT.md`:
- Line 130: Replace the stale/non-standard URL target for the [Mozilla CoC]
reference by updating the link destination to the canonical Mozilla diversity
page (use https://github.com/mozilla/diversity) so the `[Mozilla CoC]` reference
resolves to the standard enforcement ladder; edit the link text target in the
CODE_OF_CONDUCT.md entry that defines `[Mozilla CoC]` accordingly.
- Around line 5-6: Replace the incorrect word "harass-free" with
"harassment-free" in CODE_OF_CONDUCT.md so the pledge matches the canonical
Contributor Covenant phrasing; locate the sentence containing "We as members,
contributors, and leaders pledge to make participation in our community a
harass-free experience for everyone" and update it to use "harassment-free
experience for everyone."

In `@crates/uselesskey-bdd/features/pgp.feature`:
- Around line 119-122: The scenario titled "PGP user ID sanitizes special
characters" conflicts with its assertion — it currently checks that the raw
label "Test!@#User" is preserved via the step 'Then the PGP user ID should
contain "Test!@#User"'; either rename the scenario to e.g. "tolerates special
characters in label" to reflect preservation, or change the Then-step to assert
the expected sanitized user-id value; additionally, add an assertion that the
generated PGP user ID includes the domain suffix (e.g. contains
"@uselesskey.test") or explicitly validate the full address is RFC‑5322
compliant when the label contains "@", so cases like label "Test!@#User" cannot
silently create an invalid local-part.

In `@crates/uselesskey-bdd/tests/bdd.rs`:
- Around line 3862-3869: The "again" step handlers det_corrupt_pgp_armor_again
and det_corrupt_pgp_binary_again currently ignore the variant and do no state
mutation; change them to actually produce and store a second deterministic
corruption in the UselessWorld (e.g., call the same deterministic corruption
helper used elsewhere and save the result into a new field like
pgp_corrupted_armor_second / pgp_corrupted_binary_second or convert
pgp_corrupted_armor/binary into a Vec and push the new value). Also update the
corresponding then-steps corrupted_pgp_armors_identical and
corrupted_pgp_binaries_identical to compare the two stored values from the world
instead of regenerating corruptions inline. Ensure the functions
det_corrupt_pgp_armor_again, det_corrupt_pgp_binary_again,
corrupted_pgp_armors_identical, and corrupted_pgp_binaries_identical reference
the new world fields.

In `@crates/uselesskey-core/src/negative/der.rs`:
- Around line 229-237: Remove the redundant assert_ne! checks in the test
derived_offset_returns_nonzero_for_nonzero_remainder: the existing assert_eq!
calls already verify derived_offset(10, 7) == 7 and derived_offset(3, 5) == 2 so
the subsequent assert_ne!(derived_offset(10, 7), 0) and
assert_ne!(derived_offset(3, 5), 0) should be deleted; optionally add a
complementary test case (e.g., within the same test or a new one) that calls
derived_offset with a selector % len == 0 scenario to assert it returns 0 to
cover the zero-remainder contract.

In `@crates/uselesskey-ecdsa/tests/ecdsa_prop.rs`:
- Around line 92-101: Add ES384 coverage by duplicating the ES256-based property
tests to run with EcdsaSpec::es384(): update kid_is_deterministic to either
parametrize over spec or add a new test (e.g., kid_is_deterministic_es384) that
uses Factory::deterministic(Seed::new(seed)) and calls fx.ecdsa("prop-kid",
EcdsaSpec::es384()) for k1 and k2, asserting k1.kid() == k2.kid(); do the same
for different_labels_produce_different_kids (or add
different_labels_produce_different_kids_es384) to create two keys with different
labels via fx.ecdsa(..., EcdsaSpec::es384()) and assert their kids differ.

In `@crates/uselesskey-interop-tests/src/lib.rs`:
- Line 1: Add the crate-level attribute to forbid unsafe code by inserting
#![forbid(unsafe_code)] at the top of this crate's lib.rs (the crate root
source), ensuring the entire crate and its tests/helpers are compiled with
unsafe code forbidden; place the attribute before any module/item declarations
so it applies crate-wide.

In `@crates/uselesskey-rustls/tests/negative.rs`:
- Around line 47-82: The helper try_handshake currently returns Ok(()) even if
the loop exits due to no progress or reaching MAX_HANDSHAKE_ITERATIONS, which
can silently hide stalled handshakes; update try_handshake to detect a stalled
handshake after the loop (e.g., check client.is_handshaking() or
server.is_handshaking() or whether either side has completed) and return a
distinct Err (or a Result enum variant) describing the stall instead of Ok(()),
so callers can fail tests that unexpectedly never finish; reference the
try_handshake function and the MAX_HANDSHAKE_ITERATIONS loop and use
rustls::Error (or a small custom error) to convey "handshake stalled" when
neither side has completed.

In `@crates/uselesskey-token/src/token.rs`:
- Around line 276-293: Rename the test function random_base62_uses_full_alphabet
to a name that accurately reflects what it asserts (e.g.,
random_base62_contains_lowercase_or_digit or
random_base62_not_limited_to_first_five) and update any references; keep the
body (the assertion checking that the suffix has at least one lowercase or
digit) unchanged and only change the test function identifier to the new,
clearer name.

In `@crates/uselesskey-token/tests/token_prop.rs`:
- Around line 1-2: The module declaration mod testutil is unused in this test
file (testutil::fx() is never called) and should be removed; either delete the
line "mod testutil;" or actually invoke testutil::fx() where needed. Locate the
unused module declaration (mod testutil) at the top of
crates/uselesskey-token/tests/token_prop.rs and either remove it entirely or
replace usages in the proptest cases to call testutil::fx() instead of
constructing Factory::deterministic(Seed::new(seed)) so the module is genuinely
used.

In `@fuzz/fuzz_targets/ecdsa_pkcs8_pem_parse.rs`:
- Line 27: The match arm that computes `how` uses the non-idiomatic
`data.get(0).copied().unwrap_or(0)` which triggers clippy::get_first; replace
that expression with `data.first().copied().unwrap_or(0)` so the `how`
assignment (the `let how = match ...` expression) uses `.first()` instead of
`.get(0)` while preserving the `.copied().unwrap_or(0) % 5` behavior.

In `@xtask/src/main.rs`:
- Around line 125-153: The feature matrix tuple list currently enumerates
combinations like "rsa+jwk" and "ed25519+pgp" but omits "ecdsa+pgp" and
"hmac+jwk"; update the tuple list (the sequence of ("name",
&["--no-default-features", "--features", "..."]) entries) to add entries for
("ecdsa+pgp", &["--no-default-features", "--features", "ecdsa,pgp"]) and
("hmac+jwk", &["--no-default-features", "--features", "hmac,jwk"]) so the matrix
covers those potential interactions.

In `@xtask/src/receipt.rs`:
- Around line 223-238: The test runner_records_coverage_percent currently
asserts the serialized JSON via string containment which is fragile; instead
read the file, parse the JSON (e.g., with serde_json::from_str into a
serde_json::Value or the Receipt struct), and assert that the coverage_percent
field equals Some(82.5) (or 82.5 in the Value). Locate the test function
runner_records_coverage_percent and replace the json.contains(...) assertion
with parsing the file contents and an equality assertion against
receipt.coverage_percent (or value["coverage_percent"].as_f64()) after calling
Runner::new, set_coverage_percent, and runner.write.
- Around line 141-143: The setter set_coverage_percent currently accepts
non-finite f64 values which later cause serde_json::to_string_pretty in write()
to fail with an opaque error; change set_coverage_percent to validate the input
with percent.is_finite() and reject NaN/±Infinity immediately (either by
returning Result<(), E> and returning an Err for non-finite values, or by
mapping invalid values to None and documenting that behavior), update the
signature and all callers accordingly, and ensure the error type/message clearly
indicates "invalid coverage percent: non-finite value" so the root cause is
surfaced before serialization.

Comment thread .github/dependabot.yml
Comment on lines +8 to +11
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding open-pull-requests-limit to the github-actions block for symmetry.

The cargo block caps concurrent PRs at 10, but the github-actions block has no limit. With weekly updates this is unlikely to be an issue, but an explicit cap (e.g., open-pull-requests-limit: 5) prevents unbounded PR accumulation if workflows update simultaneously.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/dependabot.yml around lines 8 - 11, Add an explicit
open-pull-requests-limit to the github-actions dependabot block: update the
block that currently contains package-ecosystem: "github-actions", directory:
"/", schedule: interval: "weekly" to include open-pull-requests-limit (e.g., set
to 5) so the github-actions updates are capped similarly to the cargo block and
prevent unbounded PR creation.


**Environment (please complete the following information):**
- OS: [e.g. Ubuntu 22.04, Windows 11]
- Rust Version [e.g. 1.75]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Example Rust version is below the project's MSRV.

The template shows [e.g. 1.75] but the project enforces MSRV 1.88 (per clippy.toml). Providing a pre-MSRV example could lead reporters to submit bugs from unsupported toolchain versions, complicating triage.

✏️ Proposed fix
- - Rust Version [e.g. 1.75]
+ - Rust Version [e.g. 1.88+ — see MSRV in Cargo.toml]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Rust Version [e.g. 1.75]
- Rust Version [e.g. 1.88+ — see MSRV in Cargo.toml]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/ISSUE_TEMPLATE/bug_report.md at line 28, Update the example Rust
version in the bug report template so it matches the project's MSRV: replace the
string "Rust Version [e.g. 1.75]" with an updated example such as "Rust Version
[e.g. 1.88]" and add a short note reminding reporters to use the project's MSRV
(1.88) when reproducing issues; ensure the exact template text "Rust Version
[e.g. 1.75]" is updated wherever it appears.

Comment on lines +20 to +23
- [ ] Unit Tests
- [ ] BDD Tests (`cargo xtask bdd`)
- [ ] Property Tests
- [ ] Manual Integration Tests

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding a Mutation Tests checklist item.

Since cargo xtask mutants is a first-class CI step for this project (per CLAUDE.md and the PR itself), including it in the testing checklist would make it easier for contributors to remember to run mutation tests before submitting.

📝 Proposed addition
 - [ ] Unit Tests
 - [ ] BDD Tests (`cargo xtask bdd`)
 - [ ] Property Tests
+- [ ] Mutation Tests (`cargo xtask mutants`)
 - [ ] Manual Integration Tests
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [ ] Unit Tests
- [ ] BDD Tests (`cargo xtask bdd`)
- [ ] Property Tests
- [ ] Manual Integration Tests
- [ ] Unit Tests
- [ ] BDD Tests (`cargo xtask bdd`)
- [ ] Property Tests
- [ ] Mutation Tests (`cargo xtask mutants`)
- [ ] Manual Integration Tests
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/PULL_REQUEST_TEMPLATE.md around lines 20 - 23, Add a "Mutation
Tests" checkbox to the PR checklist in the template so contributors remember to
run the project's mutation test step; specifically, update the checklist section
that currently lists "Unit Tests", "BDD Tests (`cargo xtask bdd`)", "Property
Tests", and "Manual Integration Tests" by inserting a new item like "Mutation
Tests (`cargo xtask mutants`)" adjacent to those entries (ensure the wording
matches the CLI `cargo xtask mutants` so it's discoverable).

Comment thread Cargo.toml
"crates/uselesskey-ring",
"crates/uselesskey-rustcrypto",
"crates/uselesskey-aws-lc-rs",
"crates/uselesskey-interop-tests",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find and inspect the root Cargo.toml
find . -maxdepth 2 -name "Cargo.toml" -type f | head -20

Repository: EffortlessMetrics/uselesskey

Length of output: 140


🏁 Script executed:

# Check if there's a root Cargo.toml and its workspace.dependencies section
cat Cargo.toml 2>/dev/null | head -100

Repository: EffortlessMetrics/uselesskey

Length of output: 2357


🏁 Script executed:

# Check interop-tests Cargo.toml
find . -path "*/uselesskey-interop-tests/Cargo.toml" -type f | xargs cat 2>/dev/null

Repository: EffortlessMetrics/uselesskey

Length of output: 713


🏁 Script executed:

# Search for p256, sha2, signature usage in other Cargo.toml files
find . -name "Cargo.toml" -type f ! -path "./target/*" ! -path "./.git/*" -exec grep -l "p256\|sha2\|signature" {} \;

Repository: EffortlessMetrics/uselesskey

Length of output: 267


🏁 Script executed:

# Inspect the relevant Cargo.toml files to see how p256, sha2, signature are declared
for file in ./crates/uselesskey-bdd/Cargo.toml ./crates/uselesskey-ecdsa/Cargo.toml ./crates/uselesskey-rustcrypto/Cargo.toml ./crates/uselesskey-interop-tests/Cargo.toml ./fuzz/Cargo.toml ./tests/Cargo.toml; do
  echo "=== $file ==="
  grep -A 1 "p256\|sha2\|signature" "$file" 2>/dev/null || echo "(no match or file not found)"
done

Repository: EffortlessMetrics/uselesskey

Length of output: 1644


Centralize p256, sha2, and signature in [workspace.dependencies] to resolve version inconsistency.

The interop-tests crate declares p256 (0.13), sha2 (0.10), and signature = "2" inline, breaking workspace-level version consistency. More critically, p256 is already pinned to different versions across the workspace: uselesskey-bdd specifies 0.13.2 while uselesskey-ecdsa, uselesskey-rustcrypto, fuzz, tests, and interop-tests specify 0.13. This version mismatch could cause Cargo to pull multiple incompatible versions of the same dependency, introducing silent failures during compilation or runtime.

Add these to the root [workspace.dependencies] (reconciling the p256 version to a single value) and use .workspace = true in all affected manifests, consistent with how ring, rsa, and ed25519-dalek are already managed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` at line 20, Centralize p256, sha2, and signature into the root
[workspace.dependencies] and switch the per-crate declarations to reference the
workspace to avoid version divergence: add p256 = "0.13.2" (reconciling to the
version used by uselesskey-bdd), sha2 = "0.10", and signature = "2" under
[workspace.dependencies], then in each crate manifest that currently declares
them (e.g., uselesskey-ecdsa, uselesskey-rustcrypto, fuzz, tests, interop-tests,
etc.) replace the inline version specs with p256 = { workspace = true }, sha2 =
{ workspace = true }, signature = { workspace = true } so all crates use the
single workspace-managed versions.

Comment thread CODE_OF_CONDUCT.md
Comment on lines +5 to +6
We as members, contributors, and leaders pledge to make participation in our
community a harass-free experience for everyone, regardless of age, body

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo: "harass-free" should be "harassment-free".

The canonical Contributor Covenant v2.1 pledge uses "harassment-free experience for everyone."

✏️ Proposed fix
-community a harass-free experience for everyone, regardless of age, body
+community a harassment-free experience for everyone, regardless of age, body
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
We as members, contributors, and leaders pledge to make participation in our
community a harass-free experience for everyone, regardless of age, body
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CODE_OF_CONDUCT.md` around lines 5 - 6, Replace the incorrect word
"harass-free" with "harassment-free" in CODE_OF_CONDUCT.md so the pledge matches
the canonical Contributor Covenant phrasing; locate the sentence containing "We
as members, contributors, and leaders pledge to make participation in our
community a harass-free experience for everyone" and update it to use
"harassment-free experience for everyone."

Comment on lines +1 to +2
#[allow(dead_code)]
mod testutil;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

mod testutil is unused in this file — remove or use it.

All five proptest tests construct their own Factory::deterministic(Seed::new(seed)) from a proptest-generated seed, so testutil::fx() is never called here. The #[allow(dead_code)] acknowledges but does not resolve the dead module.

If no other non-proptest test in this binary will use testutil::fx(), drop the mod declaration. If a companion tests/token.rs (separate binary) is the actual consumer of testutil, this declaration is redundant there too, since each integration test binary compiles testutil independently.

♻️ Proposed fix
-#[allow(dead_code)]
-mod testutil;
-
 use base64::Engine as _;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[allow(dead_code)]
mod testutil;
use base64::Engine as _;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/uselesskey-token/tests/token_prop.rs` around lines 1 - 2, The module
declaration mod testutil is unused in this test file (testutil::fx() is never
called) and should be removed; either delete the line "mod testutil;" or
actually invoke testutil::fx() where needed. Locate the unused module
declaration (mod testutil) at the top of
crates/uselesskey-token/tests/token_prop.rs and either remove it entirely or
replace usages in the proptest cases to call testutil::fx() instead of
constructing Factory::deterministic(Seed::new(seed)) so the module is genuinely
used.

let pem = good_pem();

// Choose corruption based on the first byte.
let how = match data.get(0).copied().unwrap_or(0) % 5 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check the actual content of the file at line 27
echo "=== Checking file at line 27 ==="
sed -n '20,35p' fuzz/fuzz_targets/ecdsa_pkcs8_pem_parse.rs

echo -e "\n=== Search for all data.get(0) instances in fuzz targets ==="
rg -n 'data\.get\(0\)' fuzz/

echo -e "\n=== Check if clippy.toml exists and its contents ==="
if [ -f clippy.toml ]; then
  cat clippy.toml
fi

Repository: EffortlessMetrics/uselesskey

Length of output: 995


🏁 Script executed:

#!/bin/bash
# Verify clippy::get_first lint details
echo "=== Verify clippy lint status ==="
echo "Checking if get_first lint exists in Rust ecosystem..."
# List the lints that clippy covers at MSRV 1.88
echo "The clippy::get_first lint was stabilized and is available in Rust toolchain"
echo "It flags slice.get(0) in favor of slice.first()"

Repository: EffortlessMetrics/uselesskey

Length of output: 285


Replace data.get(0) with data.first() — clippy get_first lint violation.

data.get(0).copied().unwrap_or(0) is non-idiomatic; clippy::get_first flags all slice.get(0) calls in favour of .first().

♻️ Proposed fix
-    let how = match data.get(0).copied().unwrap_or(0) % 5 {
+    let how = match data.first().copied().unwrap_or(0) % 5 {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let how = match data.get(0).copied().unwrap_or(0) % 5 {
let how = match data.first().copied().unwrap_or(0) % 5 {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fuzz/fuzz_targets/ecdsa_pkcs8_pem_parse.rs` at line 27, The match arm that
computes `how` uses the non-idiomatic `data.get(0).copied().unwrap_or(0)` which
triggers clippy::get_first; replace that expression with
`data.first().copied().unwrap_or(0)` so the `how` assignment (the `let how =
match ...` expression) uses `.first()` instead of `.get(0)` while preserving the
`.copied().unwrap_or(0) % 5` behavior.

Comment thread xtask/src/main.rs
Comment on lines +125 to +153
// Feature combinations: key types with output formats
(
"rsa+jwk",
&["--no-default-features", "--features", "rsa,jwk"],
),
(
"ecdsa+jwk",
&["--no-default-features", "--features", "ecdsa,jwk"],
),
(
"ed25519+jwk",
&["--no-default-features", "--features", "ed25519,jwk"],
),
(
"rsa+x509",
&["--no-default-features", "--features", "rsa,x509"],
),
(
"ecdsa+x509",
&["--no-default-features", "--features", "ecdsa,x509"],
),
(
"ed25519+pgp",
&["--no-default-features", "--features", "ed25519,pgp"],
),
(
"rsa+pgp",
&["--no-default-features", "--features", "rsa,pgp"],
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Good expansion of the feature matrix with cross-feature combinations.

Testing combinations like rsa+jwk, ecdsa+x509, ed25519+pgp, etc. catches feature-interaction compile failures that individual feature checks would miss.

One observation: there's no ecdsa+pgp or hmac+jwk combination. If those are valid/meaningful interactions, they might be worth adding for symmetry.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@xtask/src/main.rs` around lines 125 - 153, The feature matrix tuple list
currently enumerates combinations like "rsa+jwk" and "ed25519+pgp" but omits
"ecdsa+pgp" and "hmac+jwk"; update the tuple list (the sequence of ("name",
&["--no-default-features", "--features", "..."]) entries) to add entries for
("ecdsa+pgp", &["--no-default-features", "--features", "ecdsa,pgp"]) and
("hmac+jwk", &["--no-default-features", "--features", "hmac,jwk"]) so the matrix
covers those potential interactions.

Comment thread xtask/src/receipt.rs
Comment on lines +141 to +143
pub fn set_coverage_percent(&mut self, percent: f64) {
self.receipt.coverage_percent = Some(percent);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

set_coverage_percent silently accepts NaN/±Infinity, deferring a confusing failure to write().

serde_json::to_string_pretty (used in write()) returns Err for non-finite f64 values (NaN, INFINITY, NEG_INFINITY). If coverage parsing divides by zero or produces an invalid float, the error only surfaces at serialisation time with the opaque message "failed to serialize receipt" — the actual cause (invalid float) is lost.

Validate at the setter site:

🛡️ Proposed fix — validate at the setter
-    pub fn set_coverage_percent(&mut self, percent: f64) {
-        self.receipt.coverage_percent = Some(percent);
-    }
+    pub fn set_coverage_percent(&mut self, percent: f64) {
+        assert!(
+            percent.is_finite(),
+            "coverage_percent must be a finite value, got {percent}"
+        );
+        self.receipt.coverage_percent = Some(percent);
+    }

Or, if a panicking assert is undesirable, return Result<()>:

-    pub fn set_coverage_percent(&mut self, percent: f64) {
-        self.receipt.coverage_percent = Some(percent);
+    pub fn set_coverage_percent(&mut self, percent: f64) -> anyhow::Result<()> {
+        anyhow::ensure!(percent.is_finite(), "coverage_percent must be finite, got {percent}");
+        self.receipt.coverage_percent = Some(percent);
+        Ok(())
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn set_coverage_percent(&mut self, percent: f64) {
self.receipt.coverage_percent = Some(percent);
}
pub fn set_coverage_percent(&mut self, percent: f64) {
assert!(
percent.is_finite(),
"coverage_percent must be a finite value, got {percent}"
);
self.receipt.coverage_percent = Some(percent);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@xtask/src/receipt.rs` around lines 141 - 143, The setter set_coverage_percent
currently accepts non-finite f64 values which later cause
serde_json::to_string_pretty in write() to fail with an opaque error; change
set_coverage_percent to validate the input with percent.is_finite() and reject
NaN/±Infinity immediately (either by returning Result<(), E> and returning an
Err for non-finite values, or by mapping invalid values to None and documenting
that behavior), update the signature and all callers accordingly, and ensure the
error type/message clearly indicates "invalid coverage percent: non-finite
value" so the root cause is surfaced before serialization.

Comment thread xtask/src/receipt.rs
Comment on lines +223 to +238
#[test]
fn runner_records_coverage_percent() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("receipt.json");

let mut runner = Runner::new(&path);
runner.set_coverage_percent(82.5);
assert_eq!(runner.receipt.coverage_percent, Some(82.5));

runner.write().expect("write receipt");
let json = fs::read_to_string(&path).expect("read receipt");
assert!(
json.contains("\"coverage_percent\": 82.5"),
"receipt JSON should contain coverage_percent"
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Prefer deserializing the JSON to assert coverage_percent rather than using a string-contains check.

The assertion json.contains("\"coverage_percent\": 82.5") couples the test to serde_json's internal pretty-print whitespace. While 82.5 happens to be exactly representable in f64 and serde_json serializes it stably today, parsing the JSON directly is both more robust and more expressive.

♻️ Suggested refactor
-        assert!(
-            json.contains("\"coverage_percent\": 82.5"),
-            "receipt JSON should contain coverage_percent"
-        );
+        let value: serde_json::Value =
+            serde_json::from_str(&json).expect("valid JSON");
+        assert_eq!(
+            value["coverage_percent"].as_f64(),
+            Some(82.5),
+            "receipt JSON should contain coverage_percent"
+        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@xtask/src/receipt.rs` around lines 223 - 238, The test
runner_records_coverage_percent currently asserts the serialized JSON via string
containment which is fragile; instead read the file, parse the JSON (e.g., with
serde_json::from_str into a serde_json::Value or the Receipt struct), and assert
that the coverage_percent field equals Some(82.5) (or 82.5 in the Value). Locate
the test function runner_records_coverage_percent and replace the
json.contains(...) assertion with parsing the file contents and an equality
assertion against receipt.coverage_percent (or
value["coverage_percent"].as_f64()) after calling Runner::new,
set_coverage_percent, and runner.write.

@EffortlessSteven EffortlessSteven merged commit c700a6d into main Feb 20, 2026
3 of 4 checks passed
@EffortlessSteven EffortlessSteven deleted the fix/mutants-missed branch February 20, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants