pi-mutation-test
v1.3.5
Published
Pi extension: real mutation testing score for your test suite (Stryker, mutmut, cargo-mutants) — /mutation-test
Maintainers
Readme
mutation-test — Pi extension
Runs mutation testing on the current project via /mutation-test and writes a
deterministic MUTATION_REPORT.md.
Supported stacks (auto-detected):
| Stack | Tool | Marker file |
|---|---|---|
| JavaScript / TypeScript | Stryker | package.json |
| Python | mutmut 3.x | pyproject.toml, setup.py or setup.cfg |
| Rust | cargo-mutants | Cargo.toml |
The extension is a measurement tool: it reports facts (mutants, statuses, score, locations, diffs). It performs no AI analysis, suggests no fixes, and infers no business behavior.
Install
ln -sfn "$PWD" ~/.pi/agent/extensions/mutation-test(or copy the directory; then /reload in Pi, or restart Pi)
Usage
In Pi, inside the project to test: /mutation-test
Flow: detect stack → confirm install of the mutation tool if missing (uses the
project's package manager) → confirm run → run in background → write
MUTATION_REPORT.md in the project root. Full tool output is saved to a log
file in the system temp directory (path is shown on errors; the log is removed
on a clean run).
The command requires an interactive Pi session: it must confirm both the tool install and the long run. In headless/scripted sessions it refuses to run — install the mutation tool manually and re-run in the TUI.
Mutants whose status the extension doesn't recognize are excluded from the
score and reported in a dedicated Unknown statuses line, so nothing is
silently dropped.
When the stack needs it, the install step also covers the tool's own
prerequisites — e.g. Stryker requires the typescript package when a
tsconfig.json exists, so the extension installs typescript@^5 alongside
@stryker-mutator/core (or as a follow-up install when Stryker is already
present). Nothing is installed without your confirmation.
Requirements
- Node ≥ 23.6 to run the tests (
node --test "src/**/*.test.ts"uses TypeScript type stripping). - Stryker path: npm-compatible toolchain (
npx); jest/vitest/mocha detected automatically, otherwise Stryker's command runner (npm test). Projects with atsconfig.jsonalso need a resolvabletypescript5.x — the extension installs it automatically (typescript ≥ 7 / tsgo lacks the compiler API Stryker needs). - mutmut path: pytest installed; uv / poetry / pipenv / .venv detected automatically.
- cargo-mutants path: Rust toolchain;
cargo install cargo-mutants(slow, one-time).
Development
npm install # dev-only deps (@types/node)
npm test # full unit suite
npm run typecheck # tsc --noEmitThe extension has zero runtime dependencies; @types/node is a dev-only
dependency for type-checking.
Score formulas
- Stryker:
(killed + timeout) / (killed + timeout + survived + noCoverage) - mutmut:
(killed + timeout) / (total − skipped) - cargo-mutants:
caught / (caught + missed + timeout)
Scope
/mutation-test mutates only production code — never docs, markdown,
dependencies, generated files, or test files.
- Stryker (JS/TS): passes
--mutatecoveringsrc//lib/(and other conventional dirs) plus root-level code files (index.ts,main.js, …), excluding*.spec.*/*.test.*/__tests__/. Non-code files (docs, markdown, node_modules, build output, …) are excluded from the sandbox copy with--ignorePatterns, so mutation runs stay fast and focused. If no conventional source dir exists, the tool's own default scope is used. - mutmut (Python): mutmut 3.x has no CLI scope flags (config-file only),
so the project's own
[tool.mutmut]/[mutmut]settings are respected. Default behavior is already production-code-only and coverage-guided: only.pyfiles insource_paths(guessed assrc//lib//package name) that are actually called by tests. To narrow it, addonly_mutate/do_not_mutateto yourpyproject.toml. - cargo-mutants (Rust): mutates only the current crate — dependencies are
separate crates and are never mutated. To exclude files, add
-f/-eglobs or.cargo/mutants.toml(examine_globs/exclude_globs).
