Skip to content

[PUBLISHED ON NPMJS] @takk/bayesconsensus@1.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 24 Jun 11:28

STATUS: PUBLISHED ON NPMJS. This version was published to the npm registry on 2026-06-24T11:34:57Z with provenance attestation. View on npm: https://www.npmjs.com/package/@takk/bayesconsensus/v/1.0.0

STATUS: REVIEW REQUIRED, NOT YET ON NPMJS. This GitHub Release was created by the release.yml workflow. The Creator must review the contents (tag, changelog, attached commit, pack-smoke result in the workflow logs) and then explicitly run npm-publish.yml to publish this version to the npm registry.

[1.0.0] - 2026-06-24T11:17:54Z

Initial stable release. A universal, zero-runtime-dependency NPM library and CLI that resolves disagreement across a fleet of agents, judges, or models with the Dawid and Skene (1979) model, the consensus layer for multi-agent Massive Intelligence (IM) systems and non-human entities. BayesConsensus estimates, from the votes alone and with no ground truth, the latent true label of every item AND a confusion matrix for every agent, then returns a consensus label with a calibrated confidence and a per-agent reliability audit, weighting each vote by how reliable its caster has proven to be.

Added

Consensus core

  • ConsensusModel (@takk/bayesconsensus/consensus): the facade most callers use. It exposes observe (fold one vote in), observeVotes (fold many), fit (run EM now, optional since queries fit lazily), consensus (one item's maximum-a-posteriori label, calibrated confidence, and full posterior), reliability (one agent's confusion matrix, accuracy, and per-class accuracy), aggregate (every item's verdict plus every agent's reliability), labels/agents/items, snapshot, and a static fromSnapshot.

Dawid-Skene engine

  • The expectation-maximization core (@takk/bayesconsensus/dawidskene): fitDawidSkene, the standalone eStep (in log-space, normalized per item by log-sum-exp so raw probabilities are never multiplied) and mStep (soft-count confusion matrices with diagonal Dirichlet smoothing, plus the smoothed class prior), with soft (default, calibrated) and hard (Fast Dawid-Skene) inference modes. The labels are initialized from the majority vote and the M-step is run first, both deterministic and chosen to avoid label switching; the marginal observed-data log-likelihood is monotone non-decreasing and is the convergence signal.

Primitives

  • Confusion-matrix primitives (@takk/bayesconsensus/confusion): diagonalDirichletPrior, zeroCounts, normalizeConfusion (row-normalize soft counts plus the prior), logConfusion (the clamped log form), diagonal (per-class accuracy), and weightedAccuracy.
  • The vote collector (@takk/bayesconsensus/vote): the branded agentId, itemId, and label guards, the VoteSet collector, and IndexedVotes, the dense form EM consumes, where missing votes are first-class and never imputed.
  • Majority baselines (@takk/bayesconsensus/majority): majorityVote (plurality, ties broken toward the lexicographically smaller label), weightedVote, and initialSoftLabels, the deterministic EM initializer.
  • Numeric helpers implemented from scratch with no dependency: a clamp, a safe log, log-sum-exp, a softmax over log-weights, and an argmax with deterministic tie-breaking, plus a seeded mulberry32 PRNG with categorical and integer samplers so every simulated diagnostic is reproducible.

Calibration and diagnostics

  • @takk/bayesconsensus/calibration: simulateConsensus draws a fleet of known reliability and a known truth and emits votes; measureCalibration fits Dawid-Skene and majority to that simulation and MEASURES the accuracy of each against the truth, the Brier score of the Dawid-Skene posterior, and reliability bins. accuracyAgainstTruth, brierScore, and reliabilityBins are the underlying metrics. Calibration is measured, not asserted.

Independence diagnostic

  • @takk/bayesconsensus/diversity: diversityReport measures the error correlation across the fleet against a reference labelling, the assumption check Dawid-Skene needs but does not perform, and returns the mean pairwise agreement (reference-free), the mean error correlation, the effective number of independent voters N / (1 + (N - 1) * rho), and a confidence-discount factor. temperDistribution applies that factor to flatten an over-confident posterior. ConsensusModel.diversity() runs it against the fitted consensus. The unanimous-but-wrong fleet is documented as fundamentally undetectable from votes alone, where meanAgreement is the blunt signal.

Streaming inference

  • @takk/bayesconsensus/online: OnlineConsensus, a streaming Dawid-Skene model that keeps running sufficient statistics and folds each batch in with a warm-started EM step, so reliability evolves incrementally. Optional exponential forgetting decays the accumulated counts before each batch, so the model adapts to non-stationarity (an agent whose accuracy drifts is tracked, not averaged away). It is online (incremental) EM in the Neal and Hinton (1998) sense.

Tool adapter

  • @takk/bayesconsensus/adapter: bayesConsensusTool, describeTool, runTool, parseConsensusInput, toJsonSafe, and TOOL_NAME (bayes_consensus). A framework-agnostic descriptor (name, description, JSON Schema, handler) matching what MCP servers and tool-calling APIs expect, with defensive parsing of model-supplied input. It accepts only votes (item, agent, label), never any other agent state, and returns one item's result or the full report.

Audit trail

  • @takk/bayesconsensus/audit: an append-only AuditChain of consensus verdicts and decisions with a tamper-evident SHA-256 hash chain you append to and verify with verifyChain, plus sha256Hex and GENESIS_HASH. It uses the Web Crypto API, not node:crypto, so the audit surface stays node-free. It is tamper-evident, any later edit or broken link is detectable, not an unalterable record or a digital signature.

Node loaders

  • @takk/bayesconsensus/node ships loadVotes and readJsonFile, loading votes from JSON or CSV files with defensive validation. It is the only entry point that touches a Node built-in (node:fs and node:path).

CLI

  • Binary bayesconsensus exposed via package.json#bin.
  • bayesconsensus aggregate <votes.json> fits the model and prints every item's consensus verdict and the inferred class prior; bayesconsensus consensus <votes.json> <item> prints one item's label, confidence, and full posterior; bayesconsensus reliability <votes.json> prints each agent's learned accuracy and confusion matrix; bayesconsensus audit-verify <chain.json> verifies a sealed chain. Flags: --labels <a,b,c>, --mode <soft|hard>, --diagonal-prior <n>, --json, --help/-h, --version/-v.
  • Exit codes: 0 ok, 2 usage or input error, 20 a broken audit chain.

Distribution

  • Thirteen functional subpath exports, each with split import/require conditions, plus ./package.json: the root facade plus consensus, dawidskene, confusion, vote, majority, calibration, diversity, online, adapter, audit, node, and edge.
  • Dual ESM + CJS bundles built with tsup, with separate .d.ts and .d.cts type files per entry point.
  • Node-free, platform-neutral core importable in Node, edge runtimes, and the browser; @takk/bayesconsensus/edge re-exports it verbatim.
  • Zero required runtime dependencies. @takk/keymesh and @takk/modelchain are optional peer dependencies.

Documentation and examples

  • Complete project site (index.html, 404.html) and documentation set (README.md, SPEC.md, SECURITY.md, PRIVACY.md, CONTRIBUTING.md, RELEASING.md, CLA.md, CODE_OF_CONDUCT.md), with JSON-LD structured data, an Open Graph card, and a robots and sitemap pair.
  • Seven runnable, offline, deterministic examples (a quick consensus, per-agent reliability, majority vote versus Dawid-Skene, online updates with a snapshot round-trip, the tamper-evident audit trail, a fleet diversity and independence check, and online streaming with exponential forgetting).
  • A real value benchmark (benchmarks/value-benchmark.mjs) that sweeps four reliability regimes over 25 seeds each and scores Dawid-Skene against majority vote on the known ground truth; on the committed seeds Dawid-Skene beats majority by 14.0 percentage points in the mixed-binary regime and 6.7 in the mixed-ternary regime, ties on a uniformly strong fleet, and honestly underperforms by 6.5 points on a uniformly weak fleet where there is no reliability signal to learn. Every number in the docs comes from real execution against the compiled dist.

Quality

  • 86 tests across 16 suites passing under Vitest 4, including true-label and per-agent reliability recovery on a reliable-majority dataset, a non-decreasing log-likelihood across an EM sweep, simulation-measured calibration, the diversity diagnostic, streaming online inference with forgetting, and an adversarial hardening suite (degenerate inputs, thousands of votes on one item, a 12-label space, determinism, and invariants over twenty random scenarios).
  • Coverage: statements 97.14%, branches 86.30%, functions 97.71%, lines 96.89%.
  • Lint clean under Biome 2.5. Typecheck clean under TypeScript 6 in maximum strict mode (exactOptionalPropertyTypes, noUncheckedIndexedAccess, verbatimModuleSyntax, noPropertyAccessFromIndexSignature).
  • publint clean and @arethetypeswrong/cli green across all fourteen subpaths and package.json.
  • size-limit under budget on every bundle (brotli core 6.74 kB, consensus 3.68 kB, dawidskene 2.02 kB, diversity 986 B, online 1.89 kB).
  • Distribution smoke test exercising the compiled ESM and CJS artifacts and the compiled CLI spawned as a single Node process. The full suite and smoke test are re-verified on Node 24.

Security

  • Every release is published to the npm registry with npm publish --provenance, carrying a SLSA provenance attestation generated by GitHub Actions over OIDC. Consumers can verify with npm view @takk/bayesconsensus --json | jq .dist.attestations.
  • The adapter and loaders accept only votes (item, agent, label), never any other agent state, with defensive parsing of model-supplied input.
  • Tamper-evident audit trail backed by a SHA-256 hash chain, suitable as compliance evidence that the recorded verdicts were not altered after sealing. It is an integrity seal, not a signature.
  • Zero runtime dependencies, the smallest possible supply-chain surface. The node-free core uses the Web Crypto API, not node:crypto.

Licensing

  • Licensed under the Apache License, Version 2.0. The NOTICE file ships in the tarball alongside LICENSE.

Engines

  • Node >=20.0.0. Tested on Node 20, 22, and 24.