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

@graphorin/evals

v0.8.0

Published

Eval framework for the Graphorin framework. Ships scorer libraries (`code/` exact-match, regex, JSON path, predicates; `llm/` LLM-judge; `prebuilt/` toxicity / factuality / helpfulness), dataset loaders (JSONL, CSV, from-traces, generic iterable), reporte

Downloads

739

Readme

@graphorin/evals

Eval framework for the Graphorin framework. Ships scorer libraries (code, LLM-judge, prebuilt rubrics), dataset loaders (JSONL / CSV / from-traces / iterable), reporters (terminal / markdown / JSON / JUnit / HTML), a parallel runner with bounded concurrency, and regression detection that compares the current run against a stored baseline.

Project Graphorin · v0.8.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin


Status

  • Published: v0.8.0 (optional sub-pack; the full orchestrator is decoupled from @graphorin/observability per RB-17 / DEC-152).

Install

pnpm add @graphorin/evals

The package depends only on @graphorin/core and @graphorin/observability; reporters / loaders are part of the same bundle so consumers do not need additional installs.


Quickstart

import {
  runEvals,
  loadJsonlDataset,
  exactMatch,
  renderTerminalReport,
  exitOnFailures,
} from '@graphorin/evals';

const dataset = await loadJsonlDataset('./fixtures/golden.jsonl');
const report = await runEvals({
  agent,                       // anything with `run(input)` that tolerates parallel calls
  dataset,
  scorers: [exactMatch({ caseInsensitive: true })],
  concurrency: 4,
});
console.log(renderTerminalReport(report));
exitOnFailures(report);

A Graphorin Agent instance allows one run in flight - shared across workers at concurrency > 1 it throws ConcurrentRunError. Pass agentFactory: () => createAgent({...}) (one agent per worker) instead of a shared agent; see Parallel runner.


Scorers

| Scorer family | Identifiers | Notes | |---|---|---| | code/ | exactMatch, regexMatch, jsonPath, predicate | Pure-code grading. No provider call.| | llm/ | llmJudge | LLM-as-judge. Default gpt-4o-mini-class judge with temperature: 0. | | prebuilt/ | toxicityScorer, factualityScorer, helpfulnessScorer | Wrap llmJudge with a project-tested rubric. | | trajectory/ | correctToolSelected, argumentValidity, redundantCallDetection, recoveryAfterError, finalStateCorrect | Pure-code, offline scorers over a Trajectory (the tool calls a harness made). Measure harness reliability - tool selection, argument validity, redundant work, error recovery, goal state. |


Dataset loaders

| Loader | Use | |---|---| | loadJsonlDataset(path) | Read a JSONL file. Each line is a JSON object with input + optional expected / id / metadata.| | loadCsvDataset(path) | Read a CSV file (RFC 4180 strict subset). Columns map by name.| | loadDatasetFromTraces(path, { extract }) | Distil a dataset from the framework's replay log.| | fromIterable(cases) | Wrap an in-memory array as a dataset (tests / ad-hoc data).|


Reporters

| Reporter | Output | Best for | |---|---|---| | renderTerminalReport(report) | Plain text (no ANSI). | CI logs, local dev. | | renderMarkdownReport(report) | Markdown. | PR descriptions, doc sites. | | renderJsonReport(report) | Canonical JSON. | Dashboards, regression checkers. | | renderJunitReport(report) | JUnit XML. | GitHub Actions / GitLab / CircleCI. | | renderHtmlReport(report) | Self-contained HTML. | Artifact viewers. |


Parallel runner

const report = await runEvals({
  // One agent per worker: a framework `Agent` allows a single run in
  // flight per instance, so parallel workers each need their own.
  agentFactory: () => createAgent({ /* ...your agent config */ }),
  dataset,
  scorers,
  iterations: 3,            // each case run 3 times for variance estimation
  concurrency: 8,           // up to 8 parallel agent.run() calls
  signal: controller.signal,
  onProgress: (e) => console.log(`${e.index}/${e.total} ${e.caseId}`),
});

Provide either agent (one shared instance) or agentFactory (invoked once per worker, with the worker index; it wins when both are set). A shared agent is only safe when the object tolerates overlapping run() calls - a plain stub, a stateless wrapper, or concurrency: 1. A Graphorin Agent enforces one run in flight per instance (ConcurrentRunError); when a shared instance trips that guard the runner fails fast with an EvalConcurrencyError naming the remedy, instead of recording the whole dataset as scorer failures.

Every report summary carries a Wilson 95% confidence interval for the pass rate (summary.passRateCi), and, when iterations > 1, summary.passHatK - the pass^k estimate over the per-case iteration outcomes (the probability that all k iterations of a case pass).


Statistics

Sample-size-aware statistics ship as plain exported functions:

import { mean, sampleStddev, wilsonInterval, passHatK, pairedPassSignificance } from '@graphorin/evals';

wilsonInterval(18, 20);            // { lo, hi } - 95% CI for 18/20 passes
passHatK(outcomesByCase);          // pass^k over `-iter-N` outcome groups
pairedPassSignificance(a, b);      // McNemar paired test between two runs

Regression detection

import { detectRegressions, exitOnFailures } from '@graphorin/evals';

const baseline = JSON.parse(await readFile('./baselines/golden.json', 'utf8'));
const report = await runEvals(...);
const regression = detectRegressions(report, baseline, {
  maxPassRateDropPct: 5,
  maxAvgScoreDrop: 0.05,
  maxAvgDurationIncreaseMs: 250,
  // Opt-in: veto pass-rate-drop findings the McNemar paired test
  // cannot distinguish from noise at the given alpha (default 0.05).
  requireSignificance: true,
});
if (regression.hasRegressions) {
  for (const f of regression.findings) {
    console.error(`regression - ${f.kind}: ${f.message}`);
  }
}
exitOnFailures(report, regression);

Pass-rate findings are annotated with the paired regressed / improved case counts and the McNemar p-value, so a 3-point drop on 20 cases reads differently from the same drop on 2000.


Multi-format report writing

import { writeReports } from '@graphorin/evals';

await writeReports({
  report,
  outDir: './eval-out',
  formats: ['terminal', 'markdown', 'json', 'junit', 'html'],
  basename: 'golden',
});

Related decisions

  • DEC-152 - Eval split: keep evaluation interfaces in @graphorin/observability, ship the full eval framework as @graphorin/evals.

License

MIT © 2026 Oleksiy Stepurenko


Project Graphorin · v0.8.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin