test-prune
Mutation-guided test pruning: a fixer proposes deleting redundant tests and strengthening weak ones, an independent reviewer accepts or rejects each proposal…
Skill by jesdi
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/jesdi-test-prune
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: testing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Python package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/test-prune
What's inside
- Skill name
test-prune- Description
- Mutation-guided test pruning: a fixer proposes deleting redundant tests and strengthening weak ones, an independent reviewer accepts or rejects each proposal, and prune.py applies the accepted batch behind a cold mutation run and the ratchet. Use when the user says "prune tests", "test-prune", "mutation test pruning" or "strengthen weak tests", or when a scheduled job runs it with `--unattended`.
- License
- MIT
- Instructions
- 149 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (26)
- SKILL.md
- prune.py
- prune_repo.py
- prune_review.py
- prune_runs.py
- prune_source.py
- prune_strengthen.py
- conftest.py · tests/
- prune_harness.py · tests/
- test_prune_guards.py · tests/
- test_prune_inputs.py · tests/
- test_prune_review.py · tests/
- test_prune_source.py · tests/
- test_prune_strengthen.py · tests/
- test_prune_unattended.py · tests/
- gh · tests/testdata/
- .gitignore · tests/testdata/repo/
- Makefile · tests/testdata/repo/
- mutation_baseline.json · tests/testdata/repo/backend/
- concentration.py · tests/testdata/repo/backend/services/
- rebalancer.py · tests/testdata/repo/backend/services/
- conftest.py · tests/testdata/repo/backend/tests/
- test_concentration.py · tests/testdata/repo/backend/tests/
- test_rebalancer.py · tests/testdata/repo/backend/tests/
- fake_engine.py · tests/testdata/repo/
- kill_map.json · tests/testdata/repo/
SKILL.md (first lines)
# test-prune: delete what the mutation ratchet proves redundant, strengthen what it proves weak
You are the orchestrator. `prune.py` owns every git, make and file operation and every safety
guard; the subagents only write JSON files or tests. Each role is a fresh subagent with no
context from the others: the reviewer reads the fixer's proposals, reasons included, and judges
them against the code itself.
**Publishing belongs to prune.py.** In both modes you never run `git push`, `git merge`,
`gh pr create` or `gh pr merge` yourself, and neither does any subagent; `prune` and
`strengthen-finish` push their own `chore/test-*` branch and open its PR, and nothing merges.
The target repo provides the make targets `test`, `mutation`, `mutation-check`,
`mutation-baseline`, `test-candidates`, `prune-gate` and `crap`, and the layout `backend/tests/`,
`backend/mutation_baseline.json`. Every command:
```bash
python3 "<skill-dir>/prune.py" <command> [--state DIR] [--date YYYY-MM-DD]
```
Run it from inside the target repo. State lives in `<repo root>/.test-prune/`, which prune.py keeps
out of git through `info/exclude`; each command reads what the previous one wrote there. Subagents
write their JSON files there too. Never put it under `.git/`: Claude Code refuses agent writes there. Exit 0 is done (including nothing to
do), 1 is a failed make target, gate or guard, 2 is bad input or an unmet precondition; the
message names the offending ids or files. On exit 2 fix the input and rerun the same command; on
exit 1 stop and report the output.
Every command records itself in `<state>/status.json`. A CI job reads it after the headless
session (which cannot set the job's exit code) and fails the job when its `exit` is not 0; an
unattended run stays red there until the strengthen loop ends (`nothing to strengthen`, or
`strengthen-finish` exit 0). End a headless session by reporting its `reason` as the final line.
`--state` must be empty, new, or an earlier run's state dir.
When a push succeeded but `gh pr create` failed (exit 1, the branch is on origin with no PR),
open the PR by hand from `<state>/prune-pr.md` or `<state>/strengthen-pr.md` after fixing `gh`;
rerunning the command refuses because the branch exists.
**A run needs a checkout dedicated to it** for its whole duration: the CI checkout, or a worktree.
If anything else edits a file there mid-run, the run stops with exit 1 rather than overwrite it,
leaves the checkout as it is (HEAD may stay detached), names the files, and nothing is lost; keep
or discard the change, then check out the base branch. Races beyond that check are out of scope.
**Runtime.** Each cold `make mutation` takes about 30 minutes on a real repo, and a run makes
several (collect, each safety-check run, each strengthen proof). Run long commands with a timeout of
an hour or more, or in the background, and wait for them.
## Modes
- **Interactive** (default): nothing in the working tree changes before the human approves the
batch. Stop after `batch`, show its output, and run `apply` only on an explicit yes.
- **Unattended** (`collect --unattended`, run headless by the weekly CI job): only protected
candidates, at most 10 deleted test ids per run (a parametrized test goes whole, every case
counted; one with more than 10 cases is skipped, the rest left for next week), one PR from
`chore/test-prune-<date>` and one from `chore/test-strengthen-<date>`, both from the base
commit. The base branch never moves. A merge is the human's approval, so the run ends with open
PRs.
Two kinds of accepted proposal reach a human only: equivalent mutants (the skill writes no
equivalent id into the baseline) and "strengthen this candidate with this assertion" verdicts
(the skill applies no assertion to an existing candidate). `batch` prints both; unattended, every
PR body and the job summary carry them.
## Prune loop
1. `collect [--unattended | --protected-only]`. Needs a clean tracked tree on a branch. Runs the
base checks, a cold mutation run and `make test-candidates`, then writes
`fixer-input.json`. When it prints `no candidates` / `no protected candidates`, the weak spots
may still need the fixer; continue.
2. **Fixer.** Dispatch a subagent with `<state>/fixer-input.json`, read access to the repo, and
this brief: for every candidate decide `keep`, `delete` into one named test that contains it,
or `strengthen` with one named assertion; for every weak-spot group decide `strengthen`
(which test to add to or strengthen) or `equivalent` (with the argument why no test can tell
the mutant apart). A group with both kinds of mutant takes two entries, one `strengthen` and
one `equivalent`, each listing its own disjoint `mutant_ids`. Compare assertions, not coverage: a candidate whose assertions pin a value,
boundary or error the container never checks is `keep` or `strengthen`. It writes:
```json
{"candidates": [{"test_id": "...", "verdict": "keep|delete|strengthen",
"into": "<test id, delete only>", "assertion": "<strengthen only>", "reason": "..."}],
"weak_spots": [{"group": "...", "verdict": "strengthen|equivalent",
"mutant_ids": ["<subset of the group's ids, omit for all>"],
"test": "<test id or test file>", "reason": "..."}]}
```
One entry per candidate, one per group (or the strengthen + equivalent pair), no others.
3. `review-input --proposals <fixer file>` validates the file and writes
`<state>/review-input.json`: each proposal with the candidate's source and assertions and,
for a deletion, the containing test's source and assertions. A proposal's `id` is the
candidate's test id or the group; a split group's two proposals are `<group>:strengthen` and
`<group>:equivalent`.
4. **Reviewer.** Dispatch a *different* fresh subagent with `<state>/review-input.json` and read
access to the repo. Brief: accept a deletion only when every assertion of the candidate is
implied by an assertion of the `into` test (same inputs or a superset, an equal or stricter
check); covering the same lines is not enough. Accept a strengthen proposal only when the
named assertion checks behaviour a user would notice. Accept an equivalent only with a
concrete argument that no input distinguishes the mutant. Every reason names the assertion or
input it rests on. It writes, one entry per proposal:
```json
{"reviews": [{"id": "<proposal id>", "verdict": "accept|reject", "reason": "..."}]}
```
5. `batch --reviews <reviewer file>` writes `batch.json` and prints the accepted deletions (each
with its containing test and the reviewer's reason), strengthen items, equivalent proposals,
skipped deletions with the reason, and rejections. It edits nothing.
- Interactive: show that output to the human and stop. After approval, `apply` applies the
deletions, runs the safety check, restores every culprit and commits on the current branch.
- Unattended: `prune` applies the batch, runs the safety check, `make test`, commits, runs
`make prune-gate` and, only when it passes, pushes the branch and opens the PR.
**Safety check** (inside `apply` and `prune`): a cold mutation run plus `make mutation-check`
on the batch; every deletion that lets a module exceed its baseline is restored and reported.
## Strengthen loop
Runs after the prune loop, also in unattended mode, independently of the prune PR: run it even
when `prune` exited 1 (the status keeps that failure, so the job still goes red).
1. `strengthen-start` writes `<state>/strengthen-input.json` (each accepted weak-spot strengthen
item with the mutant ids it must kill) and prints the commit to build on; unattended itFrom jesdi/general-skills, MIT.
More from jesdi/general-skills
- 0.570score
backlog
jesdi
Manage a GitHub-Issues-backed backlog and a Projects-v2 work graph via five verbs.
SkillAFreshness: AClaude Code +9 - 0.570score
pr-visual-diff
jesdi
Capture before/after screenshots of UI views with Playwright and embed them in a PR.
SkillAFreshness: AClaude Code +9 - 0.565score
review-diff
jesdi
Review a branch before merge: first a gate (the repo's check command plus crap-gate), then three independent reviewers in parallel — spec (did we build what…
SkillAFreshness: AClaude Code +9 - 0.565score
pr-risk
jesdi
Merge-risk block of a PR body.
SkillAFreshness: AClaude Code +9 - 0.565score
to-openspec
jesdi
Turn settled discovery notes and a sketched data model into a spec folder in openspec shape (proposal, spec, design) under specs/<slug>/, plus ticket files…
SkillAFreshness: AClaude Code +9 - 0.565score
review-page
jesdi
One interactive HTML page for a plan review or a questionnaire, built from a fixed template.
SkillAFreshness: AClaude Code +9 - 0.561score
to-tickets
jesdi
Break a spec, plan, or the current conversation into numbered tracer-bullet ticket files under .agent/tickets/, each declaring its blocking edges and…
SkillAFreshness: AClaude Code +9 - 0.561score
babysit-pr
jesdi
Babysit an open pull request until it is merged or handed to a human.
SkillAFreshness: AClaude Code +9 - 0.555score
implement-spec
jesdi
Implement a specification in code.
SkillAFreshness: AClaude Code +9 - 0.524score
deep-quality-review
jesdi
Extremely strict maintainability review of a branch's changes: duplicated concepts, complexity that got rearranged instead of deleted, spaghetti branching…
SkillBFreshness: BClaude Code +9 - 0.524score
red-team-data-model
jesdi
Attack a proposed or existing data model for the ways it breaks under real conditions — concurrency, time windows, money, permissions — without proposing a…
SkillBFreshness: BClaude Code +9 - 0.524score
crap-gate
jesdi
Score every function a branch changed with CRAP (cyclomatic complexity × untested fraction), fail on existing functions above 15 and new functions above 9…
SkillBFreshness: BClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 23
- Last commit (this folder)
- Oct 23, 2026 (6 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/jesdi/general-skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from jesdi
- 0.570score
backlog
jesdi
Manage a GitHub-Issues-backed backlog and a Projects-v2 work graph via five verbs.
SkillAFreshness: AClaude Code +9 - 0.570score
pr-visual-diff
jesdi
Capture before/after screenshots of UI views with Playwright and embed them in a PR.
SkillAFreshness: AClaude Code +9 - 0.565score
pr-risk
jesdi
Merge-risk block of a PR body.
SkillAFreshness: AClaude Code +9 - 0.565score
review-diff
jesdi
Review a branch before merge: first a gate (the repo's check command plus crap-gate), then three independent reviewers in parallel — spec (did we build what…
SkillAFreshness: AClaude Code +9 - 0.565score
review-page
jesdi
One interactive HTML page for a plan review or a questionnaire, built from a fixed template.
SkillAFreshness: AClaude Code +9 - 0.565score
to-openspec
jesdi
Turn settled discovery notes and a sketched data model into a spec folder in openspec shape (proposal, spec, design) under specs/<slug>/, plus ticket files…
SkillAFreshness: AClaude Code +9
Cite this page
test-prune skill. Agent Mart. https://agentmart.dev/skills/jesdi-test-prune (last updated 2026-10-24)