Documentation

Forge

@statili/forge·v0.0.2-beta.0·MIT

npm install @statili/forge

Turns the output of @statili/stats into facts — structured statements that follow mechanically from the numbers, and the prose to render them.

Deterministic, not generated. The same data always produces the same claims.

Install

npm install @statili/forge

Usage

import { linear } from '@statili/stats'
import { linearFacts, render } from '@statili/forge'

const result = linearFacts({}, linear({ precision: 2 }, data))
if (!result.ok) {
  console.error(result.message, result.helpText)
  return
}

const speak = render({ labels: { x: 'week', y: 'signups' }, units: { y: 'users' } })

for (const fact of result.facts) {
  console.log(fact.kind, '→', speak(fact))
}
// trend.linear      → "Each additional unit of week is associated with an increase of 7.85 users in signups…"
// fit.significance  → "The slope of 7.85 is statistically significant (p = 8.7e-9, 6 degrees of freedom)…"
// fit.quality       → "The model accounts for 100.0% of the variation in signups — a strong fit."

Facts

A fact separates the claim from its wording, so one claim can be spoken at several lengths, in several languages, with your own axis names:

{
  kind: 'trend.linear',
  claim: { direction: 'rising', slope: 7.85, intercept: 4.55 },
  level: 'finding',
  provenance: { method: 'linear', n: 8 },
  annotations: [{ kind: 'curve', role: 'fit', method: 'linear', points: [...], domain: [1, 8] }],
}
  • claim holds numbers and typed qualifiers — never prose. JSON-serialisable, so it can serve as ground truth in a pipeline.
  • level is finding, no-finding or caveat. “There is no trend” is a positive statement, not an absence.
  • provenance records where the claim came from, including the thresholds that produced any judgement — so you can see why a fit was called “strong”, and disagree by re-rendering.
  • annotations are chart-ready: fitted curves, uncertainty bands, and markers for vertices or decision boundaries.

Rendering

render is the only place wording lives. Swap it out entirely to localise.

render({ verbosity: 'terse' })(fact)
// "signups: up 7.85 per additional unit of week."

render({ verbosity: 'full' })(fact)
// "Each additional unit of week is associated with an increase of 7.85 in signups…"

Two verbosities cover the two things a chart needs: a short aria-label and a longer text alternative. Both come from the same claim, so they cannot disagree with each other or with the plot.

Generators

linearFacts, polynomialFacts, powerFacts, exponentialFacts, logarithmicFacts, multilinearFacts, logisticFacts and loessFacts — one per model, all with the same shape.

License

MIT

Modules

  • Render

    render, renderAnnotation, AxisLabels, AxisUnits, RenderOptions

  • Types

    ClaimMap, LinearFactOptions, LogisticFactOptions, PolynomialFactOptions, PowerFactOptions, Provenance, Annotation, ClaimOf, Fact, FactKind, FactLevel, FactResult, FactResultError, FactResultSuccess, LogarithmicFactOptions, MultilinearFactOptions, RegressionMethod

  • Regression