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

@animakit/sprt

v0.1.0

Published

Sequential Probability Ratio Test (Wald 1947) — Bernoulli SPRT gating in <1ms, 0 deps. Extracted from 53 production sprints.

Readme

@animakit/sprt

Sequential hypothesis testing in <1ms with zero dependencies — before you evolve your agent's config.

Wald (1947) Bernoulli SPRT: accumulate log-likelihood ratio per boolean sample, stop at upper/lower boundaries. Pure functions, zero runtime deps, zero I/O. Extracted from the production agent of ANIMA53 sprints, three verbatim copies of the same math (source + two test files that re-implemented it inline). This package is the single source of truth.

npm install @animakit/sprt
import { createSprt, computeSprt, presets } from '@animakit/sprt';

// Streaming accumulator (freezes after terminal decision)
const sprt = createSprt(presets.animaProduction);
for (const success of [true, true, false, true, /* … */]) {
  const { llr, decision } = sprt.update(success);
  if (decision === 'accept') break;  // production: 'apply'
  if (decision === 'reject') break;  // production: 'reject'
}

// Batch mode (parity with AgentConfigEvolver's trace loop)
const state = computeSprt(
  traces.map((t) => t.quality_proxy > 0.70),
  presets.animaProduction,
  previousLlr,
);

Why this exists

@animakit/neuromorphic-router applies score multipliers from statistically approved adjustments. @animakit/sprt-evolution (future) will compute those adjustments from traces. Both need the same SPRT core and the same KeywordWeightAdjustment type. Extracting @animakit/sprt first (PACKAGE_INVENTORY order 0) unblocks both without coupling them.

Production preset — honest asymmetry

presets.animaProduction uses the exact constants from AgentConfigEvolver.evaluatePendingRecommendations():

| Boundary | Value | Meaning | |---|---|---| | upperLlr | log(19) ≈ +2.944 | Accept H1 — matches Wald α=β=0.05: log((1-β)/α) | | lowerLlr | log(0.2) ≈ -1.609 | Reject H1 — faster than symmetric Wald |

The upper boundary is textbook Wald with α=β=0.05. The lower boundary is not the symmetric partner (log(β/(1-α)) ≈ log(1/19) ≈ -2.944). Production chose faster rejection — we preserve that exactly via explicit lowerLlr, not by silently re-deriving from α/β.

For new deployments, pass alpha + beta to get symmetric Wald boundaries:

createSprt({ p0: 0.5, p1: 0.62, alpha: 0.05, beta: 0.05 });
// upperLlr ≈ +2.944, lowerLlr ≈ -2.944

Decision mapping

| Anima Core | @animakit/sprt | |---|---| | apply | accept | | reject | reject | | gathering_data | continue |

Shared type for router + evolver

import type { KeywordWeightAdjustment } from '@animakit/sprt';

const adj: KeywordWeightAdjustment = {
  agent: 'JEFE',
  direction: 'boost',
  delta: 0.05,
};

API

interface SprtConfig {
  p0: number;
  p1: number;
  upperLlr?: number;
  lowerLlr?: number;
  alpha?: number;
  beta?: number;
}

type SprtDecision = 'accept' | 'reject' | 'continue';

interface SprtState {
  llr: number;
  samples: number;
  decision: SprtDecision;
}

function createSprt(config: SprtConfig): {
  update(success: boolean): SprtState;
  updateMany(successes: boolean[]): SprtState;
  state(): SprtState;
  reset(): void;
};

function computeSprt(
  successes: boolean[],
  config: SprtConfig,
  startLlr?: number,
): SprtState;

const presets: { animaProduction: SprtConfig };

Accumulator vs batch: createSprt freezes after the first terminal decision (streaming). computeSprt always processes the full array (batch parity with production's trace loop).

Latency

100k iterations (Node 20+, consumer CPU):

createSprt().update(true)          p99 << 1ms
computeSprt(20 samples)            p99 << 1ms

Run pnpm bench in the package directory.

Parity

The test suite reproduces every scenario from:

  • Anima_core/tests/sprint48-sprt.test.ts — LLR within 1e-12, identical decisions via presets.animaProduction
  • Anima_core/tests/sprint48-router-multipliers.test.tsKeywordWeightAdjustment structural contract

License

MIT