Speccle

/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