{
  "contract": "model-behaviour-evidence",
  "contractVersion": "1.1.0",
  "schemaVersion": "1.1.0",
  "principle": "We publish the events from which model behaviour can be reconstructed — what was forecast, what was knowable when, what reality later became, and how both changed. We do not publish trust, surprise, reliability, health or best-model scores.",
  "identity": {
    "keys": {
      "forecastEventId": "one issuance of one forecast",
      "forecastSeriesId": "one model's forecasts of one subject/channel for one target time; resolvable from every feed",
      "runId": "the producing run, where the producer records one",
      "modelId": "model identity as published by /model-identity",
      "modelVersion": "version identity within that model",
      "targetContractId": "the truth definition in /target-contracts",
      "subjectId": "site, entity or grid cell",
      "targetAt": "the moment being forecast"
    },
    "note": "Every forecast-bearing record carries forecastEventId and forecastSeriesId. Peer members carry forecastSeriesId because a comparison set records no issue clock.",
    "derivation": "Keys are deterministic hashes of the identity tuple, so they are stable across rebuilds and can be recomputed by the consumer."
  },
  "joinGraph": {
    "keys": {
      "forecastEventId": "one issuance of one forecast",
      "forecastSeriesId": "one model's forecasts of one subject/channel for one target time; resolvable from every feed",
      "runId": "the producing run, where the producer records one",
      "modelId": "model identity as published by /model-identity",
      "modelVersion": "version identity within that model",
      "targetContractId": "the truth definition in /target-contracts",
      "subjectId": "site, entity or grid cell",
      "targetAt": "the moment being forecast"
    },
    "edges": [
      {
        "from": "/api/public/v1/receipts",
        "to": "/api/public/v1/model-identity",
        "on": "modelId"
      },
      {
        "from": "/api/public/v1/receipts",
        "to": "/api/public/v1/target-contracts",
        "on": "targetContractId"
      },
      {
        "from": "/api/public/v1/predictions",
        "to": "/api/public/v1/receipts",
        "on": "forecastSeriesId"
      },
      {
        "from": "/api/public/v1/model-behaviour/forecasts",
        "to": "/api/public/v1/model-behaviour/tasks",
        "on": "targetContractId"
      },
      {
        "from": "/api/public/v1/peers",
        "to": "/api/public/v1/receipts",
        "on": "members[].forecastSeriesId"
      },
      {
        "from": "/api/public/v1/evaluations",
        "to": "/api/public/v1/receipts",
        "on": "modelId + targetContractId + window"
      },
      {
        "from": "/api/public/v1/observations",
        "to": "/api/public/v1/receipts",
        "on": "subjectId + channel + targetAt"
      }
    ],
    "doubleCountingWarning": "/receipts, /predictions, /model-behaviour/forecasts, /model-scores and /accuracy can all describe the same forecast. Resolve every record to forecastEventId (or forecastSeriesId where no issue clock exists) and treat derived feeds as views, not as independent observations."
  },
  "classification": {
    "meaning": {
      "primitive_evidence": "raw recorded events — safe to build canonical ledgers and training views from",
      "derived_evidence": "our own computation over the primitives — diagnostic metadata, not primitive truth",
      "operational": "ingest and quality control — use to gate a pull, never as a training feature"
    },
    "endpoints": [
      {
        "path": "/api/public/v1/receipts",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/predictions",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/model-behaviour/forecasts",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/model-behaviour/tasks",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/observations",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/peers",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/model-identity",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/target-contracts",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/global-context",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/layers",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/sites",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/grid-cells",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/compound-risk",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/upstream/receipts",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/upstream/prospective/pairs",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/datasets",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/dataset-rows",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/identity",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/forecast-events",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/outcome-vintages",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/model-events",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/peers",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/ledger/context",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/events",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/forecast-tasks",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/outcome-vintages",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/forecasters",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/relations",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/participation",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/external/sources",
        "evidenceClass": "primitive_evidence"
      },
      {
        "path": "/api/public/v1/evaluations",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/accuracy",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/model-scores",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/model-weights",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/relationships",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/training-runs",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/model",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/model-corpus",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/census",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/models",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/meta",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/training",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/exports",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/snapshots",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/snapshot-rows",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/snapshot-file",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/upstream/scorecards",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/handoff",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/contract",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/external/contract",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/external/census",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/ledger",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/corpus/qualification-snapshot",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/contract",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/snapshots",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/census",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/handoff",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/audit",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/file",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/panel/closures",
        "evidenceClass": "derived_evidence"
      },
      {
        "path": "/api/public/v1/health",
        "evidenceClass": "operational"
      },
      {
        "path": "/api/public/v1/source-health",
        "evidenceClass": "operational"
      },
      {
        "path": "/api/public/v1/corpus/readiness",
        "evidenceClass": "operational"
      },
      {
        "path": "/api/public/v1/upstream/status",
        "evidenceClass": "operational"
      },
      {
        "path": "/api/public/v1/upstream/prospective/state",
        "evidenceClass": "operational"
      }
    ]
  },
  "clocks": {
    "issuedAt": "when the forecast was made",
    "availableAt": "when it became readable to a consumer",
    "decisionCutoff": "the latest moment a forecast still counts for that target",
    "targetAt": "the moment being forecast",
    "outcomeObservedAt": "when reality happened",
    "outcomeAvailableAt": "when that outcome became readable",
    "basis": "Every availability clock carries a basis: observed, derived or unknown. A derived clock was reconstructed and must not be treated as evidence of publication time.",
    "invariant": "issued_at <= forecast_available_at <= decision_cutoff < outcome_first_available_at",
    "audit": "Forecast feeds return a per-row clockCheck with complete, missing and violations fields. Rows with missing clocks are not treated as passing; pass clock_ok=true to receive only complete rows that satisfy the invariant."
  },
  "emission": {
    "vocabulary": [
      "forecast",
      "abstain",
      "error",
      "missing",
      "late",
      "superseded"
    ],
    "note": "Each record carries emission.state from this closed set plus emission.raw, the provider's own string. An unrecognised raw value leaves state null rather than being forced into a bucket."
  },
  "coverage": {
    "liveInventory": "https://offdiagonal.space/api/public/v1/health",
    "note": "Inventory is operational state and is read separately from this static contract. Historical rows with no recorded publication moment are labelled unknown rather than being given the issue time."
  },
  "pagination": {
    "availabilityClock": "Feeds that carry a publication clock accept available_after and available_before and page forward on that clock, so a consumer can pull exactly what became knowable since its last read.",
    "supported": [
      "/api/public/v1/receipts",
      "/api/public/v1/model-behaviour/forecasts",
      "/api/public/v1/ledger/forecast-events",
      "/api/public/v1/ledger/outcome-vintages"
    ]
  },
  "ledgers": {
    "note": "Six canonical append-only objects, so an ingest is six pulls rather than one per endpoint. They are views over the same evidence — never a second copy of it.",
    "objects": [
      {
        "object": "model_identity",
        "path": "/api/public/v1/ledger/identity"
      },
      {
        "object": "forecast_event",
        "path": "/api/public/v1/ledger/forecast-events"
      },
      {
        "object": "outcome_vintage",
        "path": "/api/public/v1/ledger/outcome-vintages"
      },
      {
        "object": "model_lifecycle_event",
        "path": "/api/public/v1/ledger/model-events"
      },
      {
        "object": "peer_set",
        "path": "/api/public/v1/ledger/peers"
      },
      {
        "object": "context_evidence",
        "path": "/api/public/v1/ledger/context"
      }
    ]
  },
  "corpora": {
    "note": "Frozen corpora are never rewritten. A new contract produces a new corpus identity; the v0.16 development snapshot keeps its own hash.",
    "kinds": [
      "development",
      "kp_model_behaviour",
      "model_behaviour_v2"
    ],
    "handoff": "https://offdiagonal.space/api/public/v1/handoff?kind=model_behaviour_v2",
    "qualificationSnapshot": "https://offdiagonal.space/api/public/v1/corpus/qualification-snapshot"
  },
  "resources": [
    {
      "path": "/api/public/v1/model-identity",
      "provides": "model identity, versions and lineage in one payload"
    },
    {
      "path": "/api/public/v1/receipts",
      "provides": "forecast events with five clocks, emission state and outcome"
    },
    {
      "path": "/api/public/v1/model-behaviour/forecasts",
      "provides": "quantiles, probabilities, ensemble summaries, abstentions and supersession"
    },
    {
      "path": "/api/public/v1/peers",
      "provides": "individual peer forecasts per comparison set, not just a spread"
    },
    {
      "path": "/api/public/v1/target-contracts",
      "provides": "what counts as truth: matching, tolerance, aggregation, finality"
    },
    {
      "path": "/api/public/v1/evaluations",
      "provides": "stored versioned metrics with sample counts and rules"
    },
    {
      "path": "/api/public/v1/corpus/snapshots",
      "provides": "frozen dataset manifests with content hashes"
    },
    {
      "path": "/api/public/v1/upstream/receipts",
      "provides": "third-party receipts, kept separate and labelled with their own clock basis"
    }
  ],
  "excluded": [
    "trust_score",
    "surprise_score",
    "reliability_score",
    "health_score",
    "risk_level",
    "best_model"
  ],
  "semantics": {
    "appendOnly": true,
    "unavailableValues": "null or an explicit state; missing evidence is never zero-filled",
    "derivedConclusions": "provider-native evidence only; trust, health, reliability, surprise and best-model claims are excluded"
  },
  "self": "https://offdiagonal.space/api/public/v1/contract",
  "generatedAt": "2026-09-09T13:10:32.207Z"
}