/tools/heatmap
@speccle/heatmap
Shipped[tool]The oracle-strength engine. It joins three files a normal test run already produces into one typed ReportModel — Speccle reads them, it never generates them. Pure and deterministic — no LLM.
The three inputs
spec.md
you write it
Your acceptance criteria, each line carrying a bracketed [AC-x] token.
mutation.json
StrykerJS
A Stryker mutation report. The vitest runner's perTest coverage analysis records which tests covered and killed each mutant.
coverage-summary.json
Istanbul / Vitest
The json-summary coverage reporter's output. The engine reads total.lines.pct — that's the naïve baseline.
The join
A criterion links to a test when the test's name contains its [AC-x] token. For each criterion, covered counts the mutants any linked test covers, killed counts the ones those tests kill, and the kill rate is their ratio. A criterion with covered mutants is strong when its kill rate is at or above the threshold (default 0.8) and weak otherwise.
Strong
Linked tests kill mutants at or above the threshold — the criterion is genuinely defended.
Weak
Tests cover the code but mutants survive — often a spec problem, not just a test gap.
Unverified
No test carries this criterion's [AC-n] token.
Inert
Linked tests exist but cover no mutants — they touch nothing the criterion defends.
The brutal denominator
The headline oracle strength is killed / totalmutants across the whole report — uncovered and surviving mutants both count against it. Mutants reached by no token-tagged test aren't forgiven either; they land in the unattributedbucket and still drag the number down. No partial credit for code nobody's tests defend.
As a library
analyse(input) → ReportModel is exposed directly; consumers import the model types from @speccle/core and render or act on the JSON however they like — exactly what this site's demo does.
usage
import { analyse } from "@speccle/heatmap";
const report = analyse({ spec, mutation, coverage });
// → ReportModel: headline numbers, criteria in spec order, unattributed bucket