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

@factsh/attainment-engine

v0.4.0

Published

Pure attainment engine — policy document in, traceable result document out. No I/O, no database, no institution specifics.

Readme

@factsh/attainment-engine

Computes CO/PO/PSO attainment for outcome-based accreditation. A policy document and a set of marks go in; a traceable result document comes out.

Pre-release, and the framework data it is usually run against is UNVERIFIED. The engine's own arithmetic is covered by hand-computed golden fixtures. The framework files in this repository — the PO statements, their counts — have not yet been checked clause by clause against an official manual, and carry verified_on: null. Do not rely on output from those for a live submission until they pass. See DISCLAIMER.md.

What it is

import { computeOffering, computeProgram } from '@factsh/attainment-engine';

// One course offering: marks in, CO and PO attainment out.
const result = computeOffering(input, policy, {
  computed_at: '2026-07-29T00:00:00.000Z', // passed in, never read from the clock
  computed_by: 'user-1',                   // optional
});

// A whole programme, from the offering results that fed it.
const rollup = computeProgram(programInput, policy, { computed_at: '2026-07-29T00:00:00.000Z' });

result carries every CO and PO value, the method that produced it, the cohort it was computed over, warnings, and a trace on each number resolving back to the marks rows it came from.

Also exported: validatePolicy (checks a policy document before you compute with it), computeInputHash (the hash that makes a run reproducible), and FrameworkMismatchError.

The properties it holds

Pure. No I/O, no database, no network, no process.env, no Date.now(), no Math.random(). Timestamps and ids are arguments. A CI gate checks this on every commit, because the moment the engine can read a clock it stops being reproducible.

Rules are data. No threshold, weight, band or scale is in the code. They live in the policy document and the engine interprets it. There is no const PO_COUNT = 11 — NBA already moved 12 → 11 once.

Reproducible. A run pins its policy version, framework version and an input hash. Recomputing an archived run must produce an identical result, which is what makes a number defensible a year later.

Honest about degradation. Where the end-semester paper is not available question-wise, the result is stamped with which fallback was used. A fallback is never presented as a full computation.

A framework mismatch is fatal. If a policy binds to one framework and the outcome set belongs to another, the engine throws rather than warns. A 12-PO computation presented for a post-2025 submission is exactly the failure that guard exists to prevent.

Two details that decide whether the numbers are right

Both have named tests; if you are reviewing this engine, review these first.

  • Choice questions. The per-student maximum sums only over attempted questions. A student who answered Q5 (CO2) and one who answered Q6 (CO3) each get their own per-CO denominator. A class-wide denominator is the single difference between a defensible number and a wrong one.
  • Best-of-N resolves per CO. The "best two of three quizzes" can be a different two for CO1 than for CO3.

Licence

Apache-2.0. The framework data in the wider repository is CC-BY-4.0 — see NOTICE.