Skip to content

ci: the mutants gate is vacuous for crates/** -- cargo mutants runs without --workspace, 0 mutants on every crate diff #4142

Closed

Description

@noahgift

The mutants job (ci.yml, blocking via gate) has never mutated a line of crate code.

CI runs cargo mutants --no-times --timeout 300 --in-place --in-diff pr.diff -- --lib at the workspace ROOT, and does not pass --workspace. .cargo/mutants.toml sets no workspace = true. Without --workspace, cargo-mutants mutates only the package in the cwd: the root facade, src/lib.rs + src/bin/, which is nearly empty. Every diff under crates/** therefore yields zero mutants, and the job passes.

Measured on real CI output (only emitted lines, not the step source the log echoes):

PR mutants run output
#3772 35686965915 INFO No mutants to filter · cargo-mutants exit: 0 · 0 mutants in diff. Pass.
#3737 35824474310 No mutants to filter · 0 mutants in diff. Pass.
#3707 35629062866 No mutants to filter · 0 mutants in diff. Pass.
#3706 35616869889 No mutants to filter · 0 mutants in diff. Pass.

Each of these PRs changes .rs files under crates/.

Locally, cargo-mutants 27.0.0, on the #4139 branch diff:

  • cargo mutants --in-diff pr.diff --list → No mutants to filter, 0 mutants.
  • cargo mutants --workspace --in-diff pr.diff --list → 269 mutants (lex.rs 136, discharge/mod.rs 107, cli discharge.rs 15, contract_walk.rs 10, lib.rs 1).

The fix is a workflow edit, so it needs the cop's check-in. Add --workspace, and keep -- --lib (a test-tool arg). Cost is the real question: the job has timeout-minutes: 60 and --timeout 300 per mutant, and a diff like #4139 would put hundreds of mutants on it. Options:

  • --workspace with -j N (copies, not --in-place);
  • a per-PR mutant cap with a RED "too many to judge" (never a silent pass);
  • nightly full-diff mutation.

Any of these beats the current state, which is a gate that cannot fail.

Found by aprender-6c [8b6b78] while preparing #4139 (EV-6a).

Activity

  1. noahgift commented on Sep 24, 2026

    @noahgift
    MemberAuthor

    Measurements the cop asked for (lambda, 48 cores, cargo-mutants 27.0.0):

    (1) Config route: no. Adding workspace = true to .cargo/mutants.toml gives unknown field 'workspace', and 0 mutants are listed. The only way to mutate crate code is the --workspace CLI flag, so the fix is a ci.yml edit.

    (2) Cost. The diff is each PR's squash commit (git diff <merge>^ <merge>); counts come from cargo mutants --workspace --in-diff <diff> --list.

    PR .rs files / +lines mutants with --workspace where CI today
    #3706 6 / 205 21 aprender-contracts 21 0 → pass
    #3707 33 / 1078 42 serve 28, apr-cli 13, orchestrate 1 0 → pass
    #3737 4 / 547 48 aprender-viz 48 0 → pass
    #3772 80 / 7899 565 contracts 278, serve 206, apr-cli 34, contracts-cli 26 0 → pass
    #4139 (open, mine) — 269 contracts 243, contracts-cli 26 —

    Wall time, measured the way CI runs it (--in-place --timeout 300 -- --lib, serial), on #3706:

    • unmutated baseline ≈ 63 s (build 40 s, -p aprender-contracts --lib 22 s);
    • each aprender-contracts mutant ≈ 85 s (rebuild plus 1.7k lib tests).

    Serially, #3706 ≈ 30 min, #3707/#3737 ≈ 60–70 min (over timeout-minutes: 60), #4139 ≈ 6.4 h, #3772 ≈ 13 h. With -j 8 copies instead of --in-place it is roughly ÷5–6 on this host. Even so, a #3772-sized diff is about 2.5 h.

    What it catches: the partial #3706 run already MISSED two mutants in merged code: crates/aprender-contracts/src/ontology/extract/json.rs:193 replace positive_control -> bool with true and :207 replace && with || in positive_control. The positive control of an extractor can be replaced by true and no lib test notices. The vacuous gate let that through.

    Caveat, measured: on this shared host, runs longer than about 2–4 minutes were ERROR interrupted mid-test (3 of 4 attempts, both detached and in the foreground). No process-group signalling exists in aprender-contracts' source, so the cause is outside the tool and not diagnosed. A CI container should not see it, but that is unverified.

  2. added this to the 0.73.0 milestone on Sep 24, 2026
  3. noahgift commented on Sep 24, 2026

    @noahgift
    MemberAuthor

    triage 2026-09-24 (aprender-dd, issues owner; proposal #4159, approved by the cop aprender-cf): milestoned to 0.73.0 — unmilestoned tooling → carry to 0.73.0 (lightest of 0.71–0.74; its debt-ratchet slice). It was (no milestone). Open PR / live branch: br:fix/4142-mutants-workspace.

  4. added
    kind:codeWork is a code change (derived rule, #4159)
    on Sep 24, 2026
  5. modified the milestones: 0.73.0, backlog on Sep 24, 2026
  6. noahgift commented on Sep 24, 2026

    @noahgift
    MemberAuthor

    triage 2026-09-24 (aprender-dd; #4159, cop ruling): moved 0.73.0 → backlog. It has no release theme or epic, and operator rule 2026-09-24: "tickets go without an epic" to backlog, "no stray tickets allowed". It had been load-balanced into 0.73.0 as tooling carry earlier today.

  7. noahgift commented on Sep 27, 2026

    @noahgift
    MemberAuthor

    Operator ruling 2026-09-27 (relayed by the cop, verbatim): "exempt the car". Release car PRs (head car/*) skip the on-PR diff-scoped mutants cap; their code is judged by mutants-nightly (uncapped, everything merged to main). Every other PR keeps MUTANTS_CAP=60. Trigger: #4429 car diff = 2203 mutants > 60, which cannot pass by construction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:codeWork is a code change (derived rule, #4159)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions