npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@precisionutilityguild/culprits

v0.2.1

Published

Spectrum-based fault localization for Vitest and Jest — ranks the lines most likely to be your bug.

Downloads

218

Readme

culprits

A test just went red. You changed 40 lines. Which one is the bug?

culprits runs your existing Vitest or Jest suite once with per-test coverage, then ranks the source lines covered disproportionately by failing tests versus passing ones. You get a short list, and every line on it comes with the failing tests that prove it.

npx @precisionutilityguild/culprits
top 3 suspects (of 8 nonzero; ranked by dstar2)

src/stats.js
  #1  L12  ochiai 0.866  dstar2 9.000  ef 3/3 (F1 F2 F3)  ep 1/8  [all-fail]
        return (sorted[mid] + sorted[mid + 1]) / 2;

That is spectrum-based fault localization (SBFL): DStar(*=2) primary, Ochiai as the first tie-break. No config, no daemon, no index, no API key, no LLM calls. Same input, same output, every time.

Usage

Run it from any repo that uses Vitest or Jest:

culprits                 # human-readable ranked list (default top 10)
culprits --json          # machine format
culprits -n 20           # show the top 20
culprits --all           # every line with a nonzero score
culprits --runner jest   # override automatic runner detection
culprits -- test/foo.js  # everything after -- is passed through to the runner

The runner's own reporter goes to stderr and the report is the only thing on stdout, so culprits --json > out.json and piping into an agent are byte-stable.

Lines covered by all failing tests (nf = 0) carry an [all-fail] badge in the human output and "coveredByAllFailing": true in JSON. It is a display marker only, never a sort key.

Runner support

| Runner | Versions | Injection | Project config | |--------|----------|-----------|----------------| | Vitest | 4+ | Custom runner through a merged synthetic config | Inherited | | Jest | 30+ | jest-circus environment via CLI; serialized in-band | Inherited |

Both are optional peers: your project needs only the runner it already uses. Detection prefers Jest when a Jest config or jest field exists, then a sole declared Jest dependency; otherwise it keeps the Vitest default. Override with --runner vitest|jest.

Exit codes

| Code | Meaning | |------|---------| | 0 | Ranking produced (≥1 failing test, coverage collected) | | 1 | Runtime/internal failure (runner crashed, no coverage collected) | | 2 | Usage error (bad flags, missing selected runner, or project coverage is on) | | 3 | Suite is green — nothing to localize |

What to expect from the ranking

How sharp the answer gets depends on your failing tests. Discrimination scales with failing-test diversity and falls with coverage breadth. Measured on real repos with seeded bugs (receipts in the repo's notes/):

  • Several failing unit tests → the right line (benchmark fixture: bug ranked #1).
  • One failing unit test → the right function. The suspects fill the culprit's neighborhood, because a single failing test cannot discriminate between lines on its own always-executed path.
  • Integration-heavy full-suite runs → module-level signal at best; innocent lines covered only by the failing integration tests float up. Scope the run to the affected area (culprits -- test/that-area) for line-level signal. On a 1275-test repo, scoping moved the seeded bug from rank 19 to inside the top 10, with all suspects in the right function.

When the evidence runs out, you are told. A wide tie means "the coverage evidence cannot narrow this further" — the tool says so rather than faking confidence.

DStar2-as-default is a measured choice, not a preference: on a 24-seeded-bug benchmark across 7 repos it was never worse than Ochiai and strictly better in 7 trials.

How it works

A runner adapter snapshots node:inspector precise coverage around every test. Vitest uses a custom runner injected through a merged synthetic config. Jest uses a custom jest-circus environment selected through CLI flags and forces --runInBand plus --maxConcurrency=1; your config, transforms, module mappings, and test match rules stay active. Captured executed sources and their source maps are converted back to original lines with ast-v8-to-istanbul. Per line, culprits counts the failing and passing tests that cover it, ranks by DStar2, and breaks ties with Ochiai.

If any test file fails to collect (a bad import, an unresolved alias, a syntax error), culprits refuses rather than ranking a partial run — run the selected runner directly to see why.

The technique is a 1997-lineage method (Reps/Ball/Das/Larus FSE '97; Tarantula, Jones et al.; Ochiai, Abreu et al.; DStar, Wong et al.) that is standard tooling in Java and was simply never shipped for JS/TS.

Limitations

  • Vitest 4+ and Jest 30+ only.
  • Module-scope (top-level) code is not ranked — it evaluates once at import time and is attributed to no single test.
  • test.concurrent tests are serialized (maxConcurrency: 1) so their coverage can be attributed; any residual overlap is flagged and excluded.
  • Coexisting with project-owned coverage conflicts with per-test collection, so culprits refuses Vitest coverage.enabled, Jest collectCoverage, and --coverage.
  • Vitest workspace / test.projects configs are not supported — the coverage runner is injected at the root and vitest does not propagate it into sub-projects, so culprits refuses. Run it inside an individual project directory instead.
  • Jest projects configs are not supported; run inside one project directory.
  • A transformed Jest file must expose a usable source map. Unverifiable files are excluded rather than mapped to guessed lines.
  • Jest requires jest-circus and the default Node environment. Custom or per-file environments and retry attempts are refused when they prevent one coverage record per reported test.

Known limitations (Jest)

Two accepted risks in the Jest runner:

  • The incomplete-run guard is count-based (numTotalTests vs recorded coverage entries), so an exactly offsetting pair of anomalies could in principle mask a partially-instrumented run.
  • Coverage of source modules shared across test files relies on V8's Debugger.enable scriptParsed replay — standard behavior, but not yet pinned by a cross-file fixture.

Part of a family

Four tools, one idea: answers grounded in what your tests actually execute — evidence an agent can't hallucinate. Pick by the question you're holding:

| Your question | Tool | |---|---| | "A test is failing — which line is the bug?" | culprits — spectrum fault localization (npm) | | "One test is failing — which function returns the wrong value?" | apd — algorithmic debugging, LLM-as-oracle (npm) | | "Where is feature X implemented?" | recon — feature location by coverage diff (npm) | | "My uncommitted diff broke the tests — which hunks?" | diffbisect — delta debugging below commit granularity (npm) |

MIT.