The Lab · 01 · MIT licensed

trustlayer.js

The rules I argue for in design reviews, written as functions so they can be tested instead of debated. Four decisions that sit between a model and a person: which verb a score becomes, whether its confidence has earned belief, when to say nothing at all, and what to show while it thinks.

What this is not. It is not a UI kit and not a model. There is no network call, no DOM, no state, no framework — four pure functions and their tests. I own the decision logic and the interface; whether the model is right is the ML team's result to defend. The visual layer is deliberately left to you, because the verb matters more than the chip it ships in.

Use it

No install step, because there is nothing to install

One file, no dependencies, standard ES module. Copy it into a project or import it from here.

// A score never reaches a screen naked — it becomes a verb first.
import { decide, calibrate, abstain, disclose } from './trustlayer.js';

const d = decide(0.92, {
  reversible: true,
  signals: [{ name: 'margin', value: '12%' }, { name: 'stale data' }],
});

d.verb              // → 'act'
d.requires.override // → true   (an act you cannot undo is not an act)
d.explain           // → 'Confidence 0.92 at or above 0.85: safe to act, with an override.'

The four decisions

Every control below runs the real module

Nothing here is mocked. The page imports trustlayer.js and calls it as you move the inputs, so what you read is what the function returns.

decide(score, options)

Pattern · Act / Review / Ignore + Reversibility

A naked number ends in a shrug: an unexplained 87% reports the model's mood and hands the user all of the work. So the score resolves to exactly one verb before it reaches the screen, and each verb carries an obligation — an act must be overridable, a review must show its reasons, an ignore must admit it is below the line. Reversibility outranks confidence: if the action cannot be undone, the model does not get to auto-act at any score.

act

calibrate(history, options)

Pattern · Calibration & Track Record

"80% sure" only means something if, across every time it said 80%, it was right about 80% of the time. This computes the standard measures of that — Brier score, expected calibration error and the worst single bin — from a history of confidence/outcome pairs. Below thirty observations it refuses to render a verdict at all, because a track record you cannot support is just another confident claim.

SaidWas right
ECE
Brier
Samples

abstain(evidence, policy)

Pattern · Provenance, Citations & Honest Refusal

In a capital-allocation workflow one fluent, wrong claim costs more than a hundred refusals, so the default policy fails toward humility: every claim carries a source, two sources corroborate, and a clear majority agree before the system speaks. When it refuses, it returns what is missing — so the interface can name the gap instead of shrugging.

answerable

disclose(elapsedMs, options)

Pattern · Latency as a trust surface

Latency stops being a performance problem and becomes a trust problem at the moment silence becomes indistinguishable from failure. Under about 200ms a spinner reads as a flicker, so show nothing. Inside the budget, show the shape of the answer. Past the budget the user is owed a sentence, not another rotation.

skeleton

Proof

The tests, running now, in your browser

The same file runs under Node with node lab/trustlayer.test.js and exits non-zero on failure. There is no test framework, because adding a dependency to a zero-dependency library would be the joke telling itself — the runner is about forty lines at the top of the file.

running
  • Enable JavaScript to run the suite, or read the assertions in the source.

Why this exists

A rule you can run beats a rule you can argue with

Every one of these decisions used to be a slide. "Don't show a naked confidence score." "Fail toward humility." "Reversibility outranks confidence." Reasonable people nodded, and then shipped the naked number anyway, because a principle has no failing state.

Written as functions, the same rules get a failing state. decide() reports review-without-reasons as a violation rather than a suggestion. calibrate() returns insufficient-data instead of a flattering number. That is the whole argument for this file existing: the trust layer is a set of decisions, and decisions can be tested.

The eight patterns these come from are documented, with live demos, in the pattern library — and each one is running in a production product. This is their logic, extracted and made checkable.