Types
# ClaimMap interface
packages/forge/src/types.ts:89interface ClaimMap {
// ── Shape of the relationship ─────────────────────────────────────────────
/** Direction and rate of a straight-line relationship. */
"trend.linear": {
direction: "rising" | "falling" | "flat";
/** Change in Y per one-unit increase in X. */
slope: number;
intercept: number;
};
/** Shape of a fitted polynomial curve. */
"trend.polynomial": {
degree: number;
leadingCoefficient: number;
shape: "line" | "parabola-up" | "parabola-down" | "cubic" | "higher-order";
/** X position of the extremum. Quadratics only; `null` otherwise. */
vertexX: number | null;
equation: string;
};
/** Growth regime of a fitted power law, y = a·x^b. */
"trend.power": {
/** The exponent b. */
exponent: number;
/** The scale coefficient a — the predicted Y at x = 1. */
scale: number;
regime: "superlinear" | "proportional" | "sublinear" | "flat" | "inverse";
/** Y is multiplied by this when X doubles: 2^b. */
doublingFactor: number;
equation: string;
};
/** Constant proportional growth or decay, y = a·e^(bx). */
"trend.exponential": {
/** The growth rate b. */
rate: number;
/** The initial value a — the predicted Y at x = 0. */
initial: number;
direction: "growth" | "decay" | "flat";
/** Y is multiplied by this for each unit step in X: e^b. */
perStepFactor:
// …truncated
Type shortened for readability — see the source for the full definition.
The complete vocabulary of everything statili can assert.
Each entry maps a {@link FactKind} to the shape of its claim. Claims hold
numbers and typed qualifiers — never prose. Adding a kind means adding one
entry here, and the renderer will fail to compile until it handles it.
# LinearFactOptions interface
packages/forge/src/types.ts:352interface LinearFactOptions extends CommonFactOptions {
/** p-value below which the slope is called significant. @default 0.05 */
significanceLevel?: number;
}# LogisticFactOptions interface
packages/forge/src/types.ts:371interface LogisticFactOptions {
/** Accuracy below this emits a caveat. @default 0.7 */
accuracyWarningThreshold?: number;
/** McFadden pseudo-R² at or above which the fit is "moderate". @default 0.2 */
pseudoR2ThresholdWeak?: number;
/** McFadden pseudo-R² at or above which the fit is "strong". @default 0.4 */
pseudoR2ThresholdStrong?: number;
smallSampleThreshold?: number;
}# PolynomialFactOptions interface
packages/forge/src/types.ts:357interface PolynomialFactOptions extends CommonFactOptions {
/** degree/n above which an overfit caveat fires. @default 0.33 */
overfitRatioThreshold?: number;
}# PowerFactOptions interface
packages/forge/src/types.ts:362interface PowerFactOptions extends CommonFactOptions {
/** |b − 1| below this counts as proportional. @default 0.1 */
nearLinearThreshold?: number;
}# Provenance interface
packages/forge/src/types.ts:290interface Provenance {
method: RegressionMethod;
/** Observations the fit was computed from. */
n: number;
/**
* The configuration that turned raw numbers into a qualifier — the R²
* thresholds behind `"strong"`, the sample-size threshold behind a caveat.
* Present only where a judgement was made.
*/
basis?: Readonly<Record<string, number>>;
}Where a fact came from, so a consumer can audit or reproduce it.
# Annotation type
packages/forge/src/types.ts:49type Annotation =
| (AnnotationBase & {
kind: "curve";
role: "fit";
/** Predicted points spanning the observed domain. */
points: readonly PredictedPoint[];
/**
* The `[min, max]` X span `points` covers.
*
* Lets a consumer tell observed from extrapolated without scanning, and
* gives it a starting point for extending the curve past the data.
*/
domain: readonly [number, number];
})
| (AnnotationBase & {
kind: "band";
/**
* `"confidence"` bounds the fitted line itself; `"prediction"` bounds a
* single future observation and is always wider.
*/
role: "confidence" | "prediction";
/** Bounds at each x, in ascending x order. */
points: readonly { x: number; lower: number; upper: number }[];
/** The confidence level the bounds were computed at, e.g. `0.95`. */
level: number;
})
| (AnnotationBase & {
kind: "marker";
role: "vertex" | "decision-boundary";
/** Position on the X axis. */
x: number;
});Data a chart can draw directly. Structured rather than encoded into strings,
so a renderer never has to parse.
Pair with
renderAnnotation for a display label — the mapping from role to
human wording lives in the render layer, not in each consumer.# ClaimOf type
packages/forge/src/types.ts:285type ClaimOf<K extends FactKind> = ClaimMap[K];The claim shape for a given {@link FactKind}.
# Fact type
packages/forge/src/types.ts:309type Fact<K extends FactKind = FactKind> = K extends FactKind
? {
/** The vocabulary of everything statili can assert. */
kind: K;
/** Structured, narrowed by `kind`. Never prose. */
claim: ClaimOf<K>;
/** Is this notable, notably absent, or a caveat on another fact? */
level: FactLevel;
/** Everything needed to audit or reproduce the claim. */
provenance: Provenance;
/** Structured, not `"drawTrendLine:1.2,0.4"`. */
annotations?: Annotation[];
}
: never;A single statement derived mechanically from a statistical result.
Written as a distributive conditional so that the unparameterised
Fact
is a true discriminated union — narrowing on kind narrows claim — while
Fact<"trend.linear"> still names one specific shape.# FactKind type
packages/forge/src/types.ts:282type FactKind = keyof ClaimMap;The discriminator of every fact statili can emit.
# FactLevel type
packages/forge/src/types.ts:25type FactLevel = "finding" | "no-finding" | "caveat";Whether a fact asserts something notable, asserts that nothing notable is
present, or qualifies another fact.
"no-finding" is a positive statement, not an absence — “there is no linear
trend” is as useful to a consumer as “there is a strong upward trend”, and
lets a fact stream stay quiet on uninteresting data instead of padding.# FactResult type
packages/forge/src/types.ts:339type FactResult = FactResultSuccess | FactResultError;# FactResultError type
packages/forge/src/types.ts:331type FactResultError = {
ok: false;
/** End-user facing, not developer facing. */
message: string;
helpText: string;
originalErrorType: string;
};# FactResultSuccess type
packages/forge/src/types.ts:326type FactResultSuccess = {
ok: true;
facts: Fact[];
};# LogarithmicFactOptions type
packages/forge/src/types.ts:367type LogarithmicFactOptions = CommonFactOptions;# MultilinearFactOptions type
packages/forge/src/types.ts:369type MultilinearFactOptions = CommonFactOptions;# RegressionMethod type
packages/forge/src/types.ts:6type RegressionMethod =
| "linear"
| "logarithmic"
| "exponential"
| "power"
| "polynomial"
| "multilinear"
| "logistic"
/** Not a regression — a smoother. Named here because provenance covers both. */
| "loess";Every method
@statili/stats can attribute a result to.