Emit a claim
The machine produced an output and, optionally, staked a falsifiable claim on it — { metric, horizon_days, expected }. "This message gets a reply within 21 days." The hash is computed client-side; the server rejects any mismatch.
An append-only, hash-chained, bitemporal record of what the machine emitted, what actually happened, and the judgment that joins the two — the closed loop that turns many instances of a system into one that learns.
Each engine ships outputs into the world. The world answers. Almost nowhere is that answer written back against the thing that predicted it.
Aletheia is the one place every engine reports to. It stores references and hashes — never copies — and computes nothing about law, obligations, or scoring. It only records what was claimed, observes what happened, and resolves the two. That discipline is what lets one ledger sit underneath a dozen very different machines and make all of them measurable at once.
Every entry is one of three kinds. Together they turn an opinion into a falsifiable claim, and a claim into a measured outcome.
The machine produced an output and, optionally, staked a falsifiable claim on it — { metric, horizon_days, expected }. "This message gets a reply within 21 days." The hash is computed client-side; the server rejects any mismatch.
Ground truth arrives from the world — a reply, a conversion, a contradiction — and is recorded as an outcome. It joins its emission by reference, or lands unmatched until a resolver or a human joins it later.
A deterministic resolver decides: correct, incorrect, or partial, with typed provenance. A nightly sweep closes anything now decidable — a late outcome, or a horizon that quietly expired.
The same emit→observe→resolve shape instruments radically different engines — cold outreach, extraction, checkout, rule assurance — with a ~20-line adapter each.
emit() once · store the returned id · carry refs.watch_version → per-version calibration for free
Only claimed emissions count. Calibration reports whether the machine's claims came true — grouped by venture, engine, metric, and methodology version, so a past report reproduces exactly.
| venture / engine | metric | claimed | resolved | hit rate | base rate | median TTO |
|---|---|---|---|---|---|---|
| panoptes / signals | actionable | 412 | 388 | 0.63 | 11 d | |
| xtracto / outbound | reply | 1,204 | 1,150 | 0.31 | 6 d | |
| pawtrait / checkout | conversion | 96 | 54 | 0.42 | 3 d | |
| pandect / rule-assurance | contradiction | 418 | 402 | 0.02 | — |
Illustrative figures — the numbers a live ledger prints. TypeScript is authoritative; the SQL view is convenience only.
The guarantees are structural, enforced by the store and the chain — not by policy or good intentions.
A database trigger rejects every UPDATE and DELETE — aletheia is append-only. Corrections are new rows, never edits. The store exposes no update verb to exploit.
Each event carries a content_hash the server recomputes, and a chain_hash over its predecessor. seq is contiguous by construction, so a gap means a genuinely missing row.
Every read filters on observed_at — when the ledger learned a fact. Re-run last quarter's report today and get last quarter's answer, exactly.
Inserts serialize under a per-insert advisory lock; the chain is assigned in one place. Retries reuse the client id as an idempotency key — the same id twice is a 200, never a duplicate.
A resolver is a pure function keyed by rule id; its horizon and expectation live in a data row. The nightly sweep is idempotent — a re-run produces identical ids and cannot double-resolve.
Node-native TypeScript, no build step. HTTP is node:http, hashing is node:crypto, Stripe signatures are verified by hand. One runtime dependency: pg.
ledger — emit, observe, resolve, verify, report, straight from the terminal.A machine that cannot see its own outcomes cannot improve. Give the fleet one honest record, and every claim it makes becomes a number you can hold it to.