contribute · corpus api v1
Have a dataset and a model? Three endpoints make it a training source.
Zeno ingests any service that speaks Corpus API v1 — the same contract QuakePulse and AntiFogo implement. There is no per-source code on our side: if the contract holds, your source enters the corpus ledger and goes through readiness gating automatically.
for an llm or codegen agent
Hand the whole contract to your assistant
skill file
https://zenodivergent.dev/zeno-corpus-source.skill.mdMachine-readable skill: full endpoint spec, hard-fail rules, a minimal FastAPI reference server and a codegen checklist. Point any LLM or agent at this URL.
prompt
Read https://zenodivergent.dev/zeno-corpus-source.skill.md and implement a Corpus API v1 server for my dataset so Zeno Divergent can train on it. Three endpoints — /meta, /entities, /observations — with cursor pagination, append-only revisions, per-channel license and availability declarations, and available_at on every model-output row.the contract
Three GET endpoints, JSON, cursor pagination
Flat layout (antifire.live/api/corpus/v1/…) or domain-prefixed (quakepulse.live/corpus/v1/air/…) — both are supported without app-specific code.
meta
GET {base}/meta
{
"version": "corpus-api/v1",
"entity_kind": "station",
"channels": [
{ "name": "obs.tmax_c", "unit": "degC",
"availability_mode": "publication_time",
"license": "CC-BY-4.0", "log_scale": false },
{ "name": "model.temp_bias_fcst",
"class": "model_output", "horizon_hours": 24,
"license": "CC-BY-4.0" }
]
}entities
GET {base}/entities?cursor=<opaque>
{
"entities": [ { "id": "station:123", "lat": 38.7, "lon": -9.1 } ],
"next_cursor": null,
"terminal": true
}observations
GET {base}/observations?entity=station:123&since=2026-01-01T00:00:00Z
{
"observations": [
{ "timestamp": "2026-08-01T00:00:00Z",
"values": { "obs.tmax_c": 31.2, "model.temp_bias_fcst": -0.8 },
"available_at": "2026-08-01T06:00:00Z",
"revision": 1 }
],
"next_cursor": null,
"terminal": true
}| endpoint | required | hard fails |
|---|---|---|
| GET {base}/meta | version · entity_kind · channels (non-empty, each with name) | version not corpus-api/v1 | "1" | "1.0"; unknown availability_mode; empty channels |
| GET {base}/entities | entities with stable unique id · next_cursor · terminal | duplicate ids; non-terminal page without cursor; repeated cursor (loop guard) |
| GET {base}/observations | timestamp (ISO-8601 + tz) · values (numbers or null) · next_cursor · terminal | model_output row missing available_at; non-numeric value; unparseable timestamp |
what gets enforced
Five rules the ingester never bends
Every violation is a loud contract error in preflight — never a quiet change to training data. These rules are the pack boundary applied to ingestion.
01
Append-only truth — corrections are new revisions
Never reorder or mutate history. A correction arrives as the same (entity, timestamp) with a higher revision; the newer row wins. Silent mutation is a contract violation.
02
Every model-output row carries available_at
The issue time is when the platform first knew the row. A model row without it is leakage into training and is rejected outright — this is the single most enforced rule.
03
Errors are not empty corpora
Return a non-2xx status and/or {"error": …} on failure. It is retried with backoff. A 200 with an empty page during an outage silently truncates training data.
04
Fail closed on semantics
Unknown contract versions, unknown availability modes, missing keys, wrong types: the ingester refuses loudly in preflight. Never guess semantics server-side either.
05
Declare provenance per channel
license, availability_mode (publication_time / ingest_time / event_time), log_scale, processing level. Undeclared license blocks the channel from training.
why it matters
A model of models is only as good as the models it watches
Zeno's core question — where does an existing model become fragile? — can only be asked where someone else's forecasts meet reality. Every source that exposes both its observations and its model outputs gives the Surprise Intelligence Model one more arena to learn that boundary in.
The corpus is already a federation of independent observation services, not one dataset: live environmental, geophysical, epidemiological and market streams, each with its own entities, cadence and forecast horizons — over a thousand tracked entities across gated and context lanes, and growing.
The current release is a 1.7M-parameter model of models, trained on a single L4 GPU with leave-one-domain-out evaluation — small on purpose, so the evidence, not the scale, carries the claim. Each domain faces pre-declared evidence gates with three claim tiers: Tier A (beats a learned baseline on representation), Tier B (operationally useful, calibrated, abstains well), Tier C (one narrow, honest signal) — and domains that clear none are refused, shipped as labelled candidates, never as evidence.
Your source doesn't need to be big or finished. Thin history accumulates honestly as a labelled context lane until it can stand on its own — the gate exists to keep claims true, not to keep people out.
- 1,560,952
- parameters in the current release
- 1× L4
- GPU the promoted run trained on
- 5+
- independent domains already in the corpus
- 1,000+
- tracked entities across lanes
- 3 + refused
- claim tiers — and refusal is a first-class outcome
- 0
- lines of per-source code needed on our side
after the contract holds
What your source becomes
The source is swept into the corpus ledger with its true span, entity count, cadence and target prevalence. A readiness gate — entity floors, minimum history, forecast-era availability, license — decides whether it earns gated training weight, contributes as lower-weight context, or accumulates until ready.
Reporting ready: false while history accumulates is a supported, honest state — AntiFogo does exactly that today. A thin source is never discarded; it is weighted as context until the evidence exists.
source contract
QuakePulse — five-domain observation corpus
Air, earth, agriculture, marine and urban streams, read live from quakepulse.live/api/corpus/v1. Channel classes, providers and resolutions below come from the partner's own metadata.
contract
Domains and channel classes
Reading the live contract…
measured
What each domain is actually worth right now
Verdicts from the corpus ledger, measured against this contract on 2026-09-01. A lane never rises above the posture the source itself can evidence.
rules
How Zeno reads this feed
- Only row-level evidence counts. A row's sources list and its lineage.status (complete / partial / unavailable) decide what may be claimed. Configured providers, channel descriptions, model names and a live flag prove nothing.
- Open Cosmos is claimed only with a persisted scene. Marine ROI analyses and urban/agriculture scene metrics carry scene IDs and capture times; a sentinel burn_area_upwind_7d: 0 is a no-scene marker, not evidence.
- Three clocks stay separate. Event timestamp, publication available_at and platform ingested_at are all preserved; splits key on availability.
- Intervals stay intervals. Lower and upper forecast bounds are kept as their own channels rather than collapsed into a point.
- Model channels are references, not truth. Partner forecasts enter as reference predictions the model is measured against — that disagreement is the signal.
- Absence is checked, not assumed. Source health is polled before a missing stream is treated as a real quiet period.
source contract
AntiFogo — wildfire municipality corpus
Portugal mainland wildfire risk, read live from antifogo.pt/api/corpus/v1. Everything below is fetched from the partner's own capabilities and provenance manifests, so it cannot drift from what they actually serve.
contract
What the corpus is
Reading the live contract…
This is why AntiFogo does not move the wildfire gate yet, and the source says so itself: its own readiness block reports the lane as not ready, with a handful of complete observation days against the threshold it declares. The feed is live, correctly specified and rich in lineage — every value names the station or product behind it — but a short window of real days is not a run of quiet ones. Zeno records the coverage gap and refuses to score wildfire until the history is long enough to split chronologically. The corpus ledger therefore carries this lane at weight zero rather than at a flattering fraction.
next