Test · Configuration
The Test family is opt-in. Off by default — turn it on once
your project has (or is willing to wire up) an lcov.info produced
by cargo llvm-cov, pytest --cov, nyc, or scoverage. heal
never executes tests itself; everything that needs the test suite
to actually run (flakiness, mutation score, runtime trends) stays
out of scope.
For what each metric flags, see Test › Metrics. For the bundled skills, see Test › Skills.
Quick enable
Section titled “Quick enable”[features.test]enabled = true
[features.test.coverage]enabled = trueDefaults cover Rust / TypeScript / JavaScript / Python / Go / Scala
test conventions and the four conventional lcov.info paths. Most
projects don’t need to override anything.
If you don’t have an lcov.info yet, run the bundled setup
skill — it inspects your stack and proposes the reporter wiring.
claude /heal-test-reporter-setupFor the full skill contract see Test › Skills.
[features.test]
Section titled “[features.test]”[features.test]enabled = false # master switchtest_paths = [ "tests/**", "**/*_test.rs", "**/*.test.ts", "**/*.test.tsx", "**/*.test.js", "**/*.test.jsx", "**/*.spec.ts", "**/*.spec.tsx", "**/*.spec.js", "**/*.spec.jsx", "**/__tests__/**", "**/*_test.go", "**/test_*.py", "**/*_test.py", "**/*Test.scala", "**/*Spec.scala",]enabled(defaultfalse) — master switch. While false, every test observer is a no-op.test_paths(default: language conventions above) — gitignore- syntax globs that mark which source files are tests. Theskip_ratioobserver walks these files; every Finding whose primary file matches is also taggedis_test_file = true.
When test_paths is empty, heal falls back to a built-in
heuristic covering the same conventions.
is_test_file flag
Section titled “is_test_file flag”When [features.test] is enabled, every Finding gains an
is_test_file: bool flag. Skills filter on this to read test- and
production-side severities independently — /heal-test-review
focuses on test findings; /heal-code-review focuses on
production findings.
The flag is omitted from JSON output when false, so projects that
don’t enable the test family see byte-identical latest.json
content to before.
[features.test.coverage]
Section titled “[features.test.coverage]”[features.test.coverage]enabled = falselcov_paths = [ "lcov.info", "coverage/lcov.info", "target/llvm-cov/lcov.info", "coverage/lcov-report/lcov.info",]enabled(defaultfalse) — sub-feature switch. Keep[features.test]on but[features.test.coverage]off when you wantis_test_filetagging andskip_ratiowithout yet wiring up a reporter.lcov_paths— project-relative paths probed in order. First existing file wins; the rest are ignored. Missing files are silent — no warning at startup.post_commit_refresh(default unset) — optional shell command the post-commit hook spawns in the background to re-run your reporter after every commit. The process is detached and its output discarded so your commit flow doesn’t wait. Pair it with the same command/heal-test-reporter-setupproposes (cargo llvm-cov --workspace --lcov --output-path lcov.info --locked --ignore-run-fail,pytest --cov=..., etc.) so the nextheal statusreads freshlcov.info. Skipped silently when[features.test]or[features.test.coverage]is off.
heal reads what your CI / local reporter produces. The default probe order covers:
| Reporter | Path written |
|---|---|
cargo llvm-cov --lcov | target/llvm-cov/lcov.info |
pytest --cov --cov-report=lcov | coverage/lcov.info |
nyc --reporter=lcov | coverage/lcov-report/lcov.info |
scoverage (Scala) | varies; symlink to lcov.info if needed |
The lcov reader is permissive — it tolerates unknown record types and recovers totals from per-line records when reporters omit the summary fields, so most reporter dialects work out of the box.
Calibration
Section titled “Calibration”Two new sections appear in .heal/calibration.toml when you run
heal calibrate --force with the test family on:
[calibration.coverage_pct]# Heal stores INVERTED values (100 - coverage_pct) so the same# `value >= p95 → Critical` cascade applies as for the rest of the# metrics — worst still maps to Critical.p50 = 30.0 # 70% coveragep75 = 50.0 # 50% coveragep90 = 70.0 # 30% coveragep95 = 85.0 # 15% coveragefloor_critical = 95.0 # ≤ 5% coverage → Critical regardless of percentilefloor_ok = 25.0 # > 75% coverage → Ok regardless of percentile
[calibration.skip_ratio]p50 = 0.0p75 = 1.0p90 = 5.0p95 = 10.0floor_critical = 20.0 # > 20% skip → Criticalfloor_ok = 0.5 # < 0.5% skip → OkThese are the literature-anchored fallbacks heal uses until you
run heal calibrate --force. Floors belong in config.toml, not
here, so they survive recalibration:
[metrics.coverage_pct]floor_critical = 90.0 # tightens to "≤ 10% coverage → Critical"
[metrics.skip_ratio]floor_ok = 0.0 # any skipped test surfaces(coverage_pct overrides apply to the inverted form —
floor_critical = 90.0 means ”≤ 10% line coverage”, not ”≤ 90%”.)
Post-commit nudge
Section titled “Post-commit nudge”When [features.test.coverage] is on, the post-commit hook adds an
indented second line to the nudge:
heal: recorded · 3 critical, 7 high · heal status · 2 uncovered hotspotThe count is the number of coverage_pct findings at High or
Critical severity that also carry hotspot=true. The line is
suppressed when the coverage feature is off.
Strict by design
Section titled “Strict by design”Like every other section, [features.test] and
[features.test.coverage] reject unknown keys:
[features.test]test_path = ["tests/**"] # ✘ unknown — heal errors here # (it's `test_paths`, plural)