Tollbridge Docs

Decisions

The decision-record anatomy (16 fields), deterministic policy replay, and outcome/calibration honesty.

Every engine call produces a DecisionRecord — one row in the append-only decisions ledger, rendered to customers as: probability P that event obtains within horizon, conditional on conditions, computed from input_hash, at confidence, with freshness per input and calibration adequacy stated.

Record anatomy — the 16 fields

The ledger row mirrors the decisions table 1:1 (§1.8 DecisionRecord):

#FieldMeaning
1decision_iduuid PK — stable identifier across reads and replays
2timestampwhen the decision was recorded
3assetBTC | ETH | SOL
4chainbase (v1)
5input_hashprovenance hash of the journaled inputs (idempotency key)
6state_hashhash of the feature state at decision time
7feature_versionfeature-engine version
8question_versionsignal definition version (S01..S11)
9jev_versionjudgment-engine version
10probabilitythe recorded probability (0 = no claim made)
11confidencethe recorded confidence (0 = no claim made)
12policy_versionsealed ruleset that produced the verdict
13decisionpublish | monitor | escalate | suppress | insufficient_confidence | stale_input
14actionnone | record | alert | webhook | escalate_human — the vocabulary deliberately excludes any execution verb
15payment_idFK to the payments ledger (null on free surfaces)
16outcome_idone-shot link to the realized outcome (nullable)

The action vocabulary excludes execution verbs by design: Tollbridge renders verdicts, not trades.

Replay semantics

Replay (POST /v1/decisions/{id}/replay, free) is deterministic and policy-only:

  • The journaled decision inputs are re-verified against the ledger row's input_hash, then re-evaluated under the requested sealed ruleset ({"ruleset_version": "1.0.0"} or the recorded default).
  • The response carries { decision_id, original_verdict, replayed_verdict, matched_rules, policy_version, deterministic: true }.
  • Inputs that cannot be verified → 409 REPLAY_INPUT_LOST — never a fabricated replay.

Model replay is out of scope in v1 — stated honestly. A live model re-run ("replay with the current model") would be a NEW decision, not a replay: model drift and refusal semantics change what jev would have said. Replays are policy-only by construction; a new decision costs a new payment and creates a new ledger row.

Outcome + calibration reporting

Realized outcomes link back to decisions one-shot (outcome_id), and the calibration service reports bucketed reliability over the ledger:

  • Calibration output is never silently self-tuned; every learned change ships as a sealed, published release with its measured proof — see Decision intelligence.
  • Any bucket with inadequate sample size renders as "insufficient sample — no calibration claim" (the insufficient-sample honesty rule): a handful of outcomes is not a calibration curve, and Tollbridge will not pretend otherwise.
  • Attribution keys (event_definition_hash, jev_version, question_version, policy_version) keep every number traceable to the methodology that produced it.

Calibration in a served decision body

When a decision's number is reconciled with a frequency counted on the provider's own market history, the served decision body carries a calibration block describing that basis in plain terms:

"calibration": {
  "basis": "measured_history",
  "source": "the venue's own price history",
  "observations": 7385,
  "assets": ["BTC", "ETH", "SOL", "HYPE", "DOGE"],
  "window_days": 208,
  "starting_condition": "allow"
}
  • observations is how many historical outcomes the frequency was counted over.
  • window_days is the history's span (or null when the source does not record one).
  • starting_condition appears only for a question whose number is conditioned on the account's state at the moment the decision was made.
  • The block is present only when a measured frequency was actually applied. A refusal, a question with no measurable frequency, or a disabled control omits it — absence is the honest signal, never a placeholder.

The calibration block reports the basis of the number; it does not change what the number is. The probability stays the model's forecast, reconciled with measured history.

Honest refusals

Stale/degraded inputs, inadequate baselines and unavailable surfaces are 200 responses with the refusal recorded as the decision — probability and confidence are 0 ("no claim"; the decision field carries the truth):

Recorded decisionMeaning
stale_inputan input breached its staleness budget or arrived degraded
insufficient_confidencejev refused (insufficient_sample) or a degenerate baseline
suppressjev refused (out_of_scope / unresolvable_event) or the surface is unavailable

A provider being down is NOT a decision — it surfaces as a typed error and records nothing.

Where decisions appear

On this page