v0.1 · MIT · ESM · Node 20+

Risk metrics from your
commit history. Always reproducible.

@nkwib/pr-engine turns a list of git commits into per-file risk metrics. No network. No LLM. No database. Same input always produces the same output, bit-for-bit.

$ npm install @nkwib/pr-engine

Deterministic by construction

No Date.now(), no Math.random(), no unordered iteration in business logic. Same input → same output, always.

~7.5 ms over 10 k commits

Full pipeline median: analyze() processes 10 000 commits / 500 files in ~7.5 ms. Cochange is the heaviest engine and still fits in 5 ms.

No fabrication

Every numeric claim points to real commit SHAs in groundedIn — or it's null. The engine never defaults to 0 when it has no signal.

Inputs in, data out

No fetch, no octokit, no child_process, no DB clients. The package is a pure function from CommitRecord[] to risk metrics.

Five composable engines

mineCommits · computeChurn · computeCochange · computeHotspots · computeRisk. Use analyze() or wire them up yourself.

Versioned schema

Output carries an ANALYSIS_SCHEMA_VERSION. Pin to the major when you integrate; new metrics arrive as new top-level keys without breaking parsers.

Bring your own git driver

The engine consumes CommitRecord[] — pure data. Two git log passes, parsed by the bundled parseCommitMetadata / parseCommitFiles, and you have a full input. The CLI package ships a ready-made LocalAdapter if you'd rather skip the wiring.

Producing CommitRecord[]
import {
  parseCommitMetadata, parseCommitFiles, type CommitRecord
} from '@nkwib/pr-engine';

const META  = "%x1e%H%x1f%P%x1f%aN%x1f%aI%x1f%B";
const FILES = "\x1eCOMMIT %H";

const meta  = parseCommitMetadata(metaStdout);
const files = parseCommitFiles(fileStdout);

const commits: CommitRecord[] = meta.map(
  (m) => ({ ...m, filesTouched: files.get(m.sha) ?? [] })
);

Pure data in. Grounded metrics out.

No clock. No PRNG. No network. Run twice, get the same bytes.

@nkwib/pr-engine Deterministic engine — mining, churn, cochange, hotspots, risk