{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://chainchoice.io/methodology/spec/signal-taxonomy.schema.json",
  "title": "ChainChoice Signal Taxonomy",
  "description": "Canonical signal taxonomy for the cognitive stack's Market layer (level 5) and Drift layer (level 7). Signals are the time-anchored facts the engine consumes — yields, fees, custody state, regulatory events, on-chain TVL movements. Every signal must declare a kind, a freshness window, and a source.",
  "type": "object",
  "required": ["signal_id", "kind", "observed_at", "source", "value"],
  "properties": {
    "signal_id": {
      "type": "string",
      "description": "Stable identifier of the metric stream, e.g. 'defillama:aave-v3:eth:supply_apy'."
    },
    "kind": {
      "type": "string",
      "enum": [
        "yield_apy",
        "trading_fee_bps",
        "withdrawal_fee_pct",
        "tvl_usd",
        "spread_bps",
        "custody_disclosure_change",
        "regulatory_event",
        "incident",
        "market_regime",
        "btc_dominance",
        "volatility_30d",
        "liquidity_score"
      ]
    },
    "observed_at": { "type": "string", "format": "date-time" },
    "valid_for_seconds": {
      "type": "integer",
      "minimum": 1,
      "description": "How long this observation should be treated as fresh. Engine flags drift past this window."
    },
    "source": {
      "type": "object",
      "required": ["name", "trust_tier"],
      "properties": {
        "name": { "type": "string", "examples": ["defillama", "coingecko", "sec.gov", "esma.europa.eu", "cftc.gov", "editorial_verification"] },
        "url": { "type": "string", "format": "uri" },
        "trust_tier": { "type": "string", "enum": ["primary", "aggregator", "secondary", "editorial"] }
      }
    },
    "subject": {
      "type": "object",
      "description": "What the signal is about.",
      "properties": {
        "provider_id": { "type": "string" },
        "asset": { "type": "string" },
        "chain": { "type": "string" },
        "jurisdiction": { "type": "string", "description": "ISO 3166 alpha-2 or 'eu', 'global'." }
      }
    },
    "value": {
      "oneOf": [
        { "type": "number" },
        { "type": "string" },
        { "type": "object" }
      ],
      "description": "The observed value. Shape depends on kind."
    },
    "delta_pct_24h": { "type": ["number", "null"], "description": "Optional change vs 24h ago." },
    "anomaly_score": {
      "type": ["number", "null"],
      "minimum": 0,
      "maximum": 1,
      "description": "0 = within normal range; 1 = extreme outlier vs trailing window."
    }
  }
}
