/test-improve¶
File: skills/test-improve/SKILL.md
Role: orchestrator.
/test-improve is the consolidated analyze-then-improve orchestrator for
legacy or in-flight test suites, and one of the plugin's two multi-phase
pipelines with inter-phase human gates (the other is /ship).
It defaults to lightweight ceremony, prompts for heavier capabilities
(Gherkin extraction, mutation testing, refactor-for-testability) only on
demand, and always baselines coverage (and mutation, when enabled) before any
test change.
This page is the canonical phase reference. For where /test-improve sits
among the plugin's other commands see workflows.md; for how it
fits the wider agent architecture see
agent-architecture.md.
Phases¶
Each phase writes a progress file to
.claude/memory/test-improve/<slug>/phase-<n>.md so /continue (and --from-phase)
can resume.
Execution order. Phases keep their historical identity numbers (Phase 1
is always Analyze, Phase 2 is always Baseline, etc.), but Baseline (Phase 2)
and Derive Gherkin (Phase 3) execute before Analyze (Phase 1) so
/test-health can use documented-but-untested Gherkin scenarios as a
coverage signal: 0 → 2 → 3 → 1 → 4 → 5 → 6 → 7 → 8 → 9. Phase 7 and Phase 8
are not alternatives — when Phase 6 returns [y], both run in sequence;
otherwise Phase 8 follows Phase 6 directly. When the BDD binding mode is
none, Phase 3 is skipped and the sequence becomes
0 → 2 → 1 → 4 → 5 → 6 → 7 → 8 → 9. The list below follows this execution
order, not numeric order. The phase-start banner prints a separate
Step <position>/<total> — Phase <N>: <name> counter — <position> is a
running count of phases printed so far this run (never a fixed per-identity
slot), and <total> is computed per run (base 9, -1 when BDD binding mode
is none, +1 once Phase 6 enters Phase 7) rather than a hardcoded 9 or 10.
- Phase 0 — Approach contract. Batched prompt (Enter accepts all
defaults): mutation mode
[kill-loop](off/kill-loop/baseline+kill-loop), BDD rubric[none], refactor[no-refactor], quality targets, sink (--parent <url>vs local files), and the all-or-none code-lookup install (explicity/n, not part of Enter-accepts-all). An Enter-through run now performs the mutant-kill loop by default. Go stack shows the alpha go-mutesting advisory before the mutation prompt. Answers are immutable for the run. A stated coverage target that is structurally unreachable underno-refactoris surfaced here as[w] waive / [s] switch to refactor-allowed / [c] continue as-is, computed byscripts/coverage_gap_ranking.py; with no coverage report on disk yet the check is recordeddeferredand re-run at Phase 2 (#1787). - Phase 2 — Baseline (before any test edit).
/coverage-baseline --workflow test-improveunconditionally;/mutation-testing --baseline --workflow test-improveonly inbaseline+kill-loopmode (offandkill-looptake no baseline). Go = advisory-only marker. Honest score = hard kills, timeouts separate. Thenscripts/coverage_gap_ranking.pywritesdata/coverage-gap-ranking.json— per-module buckets ranked by uncovered lines descending, each markedseam: established|absent— the targeting input Phases 1, 4, and 5 read instead of mutation survivors (#1786), and the place a deferred Phase-0 conflict check resolves. - Phase 3 — Derive Gherkin (conditional).
noneskips entirely (Phase 1 follows Phase 2 directly in that case);xunit-with-annotationswrites.featurefiles without a runner;bdd-runnerwires the native parser. - Phase 1 — Analyze. Delegate to
/test-health(sole worker). No separate calls to/cd-test-architecture,/test-design,/mutation-testing. Whenever a coverage percentage is a stated goal, the improvement plan's coverage-driven items are ordered bycoverage-gap-ranking.jsonrank, never by mutation survivor count — survivors order work only within aseam: establishedmodule (#1786). Mutation section respects Phase-0 setting. A separate, direct classification pass persists a before-snapshot of test counts by MinimumCD type totest-counts-before.json.--analyze-onlyruns Phase 0 then this phase directly, bypassing the Baseline/Derive-Gherkin ordering above, and exits with no baseline captured. - Phase 4 — Plan fixes.
/issues-from-assessment --workflow test-improvepartitions findings intoNO_REFACTOR(Phase-5 Stories) /REFACTOR_REQUIRED(deferred to Phase 7) /LOW_VALUE(advisory-only). The NO_REFACTOR Story set is written incoverage-gap-ranking.jsonrank order when a coverage percentage is a stated goal (#1786). - Phase 5 — Improve without refactoring. Per Story:
/build(no-refactor) →/coverage-delta --workflow test-improve --story <id>→scripts/coverage_delta_steering.py(three consecutive near-zero-delta Stories exit 3 and prompt[t] re-check Phase-1 targeting / [c] continuemid-phase, #1790) →mutation-killagent, dispatched once per module batch (--file <every story file in the batch> --max-rounds 3 --target-honest-score <Phase-0 mutation target>, #2030;[c/r/w/q]on residuals) →scripts/mutation_yield_steering.pyat the batch boundary (two consecutive batches killing fewer than the minimum net survivors exit 3 and prompt the same[t] re-check Phase-1 targeting / [c] continue, #2033 — the #1790 mechanism ported to the more expensive lane, sharing its status vocabulary and exit-code contract). End-of-phase review loop runs/test-design --sinceand/code-review --sincein parallel,/apply-fixesthen re-run, cap 2 iterations,[r/w/q]escalation. Evidence inphase-5-review.json. - Phase 6 — Refactor decision prompt.
[y] enter Phase 7 / [b] backlog and skip to Phase 8 / [q] quit. The letteryis deliberately chosen overr, which is already claimed by mutation-kill's[c/r/w/q](retry) and the review loop's[r/w/q](revise). - Phase 7 — Refactor-for-testability (conditional). Only when
[y]. Seam-only production-code changes; existing tests are immutable. Each Story precondition-checks the paired Phase-5 baseline is closed and green. Same end-of-phase review loop; evidence inphase-7-review.json. - Phase 8 — Validate.
/quality-targets-converge --workflow test-improve --refactor-mode <value>— threading Phase 0'sno-refactor/refactor-allowedvalue keeps the coverage-gap dispatch table from proposing a[Refactor-for-testability]Story once no-refactor was already chosen at Phase 6; it writes arefactor-backlog.mdentry instead. Mutation off = skipped (not waived). Go = advisory-only. Coverage < 90% in no-refactor mode →[y/n]re-run-in-refactor-allowed prompt lists backlogged items and recordscoverage_reprompt_fired: trueinphase-8.md(so Phase 9's close-out prompt below doesn't re-ask). The identical classification pass from Phase 1 recounts test-by-type intotest-counts-after.json./handoffis suggested here, and after Phase 1 and the Phase 5/7 review loops — the context-heaviest boundaries. - Phase 9 — Executive-summary report. Interpolates the shipped
templates/executive-summary.mdfrom the git-tracked.dev-team-reports/test-improve/<slug>/data/directory plus.claude/memory/test-improve/<slug>/process/audit state to.dev-team-reports/test-improve/<slug>/report-<date>.md. 10 numbered sections; empty sections render "Not applicable" (never omitted). § 1 includes a "Tests by type" table (Baseline/Achieved/Δ per MinimumCD type). § 7 foregrounds a seam-needed/behavior-gained/estimated-risk table sourced fromrefactor-backlog.md. Parent tracker (or.claude/plans/test-improve/FEATURE.md) is updated with a link to the report. Report is regeneratable from memory. After Phase 9, ifrefactor-backlog.mdhas entries and Phase 8's re-run prompt never fired this run, a close-out[y/n]prompt asks whether to re-run with refactor-allowed mode.
Arguments¶
/test-improve <repo-path> [--parent <url>] [--analyze-only] [--from-phase <n>] [--stack <id>]
| Flag | Behavior |
|---|---|
<repo-path> |
Positional. Path to the repository to improve (required). |
--parent <url> |
Post progress and Stories to this tracker issue URL instead of local plan files. |
--analyze-only |
Run Phase 0–1 only; skip improvement phases. |
--from-phase <n> |
Resume from phase n (requires existing .claude/memory/test-improve/<slug>/ files). |
--stack <id> |
Override auto-detected stack identifier (e.g. go, python, java). |
/continue resumes any phase from .claude/memory/test-improve/<slug>/phase-<n>.md;
--from-phase <n> does the same explicitly and never re-prompts Phase 0.
--analyze-only runs Phase 0 + Phase 1 and exits before baseline capture.