{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://kdc.bussetech.com/schema/signals.schema.json",
  "title": "kdc signal",
  "description": "One claim from one source about one site. Append-only; conflicting signals coexist by design (signal > canon).",
  "type": "object",
  "required": ["id", "attribute", "value", "source_url", "observed_date", "collected_by", "confidence"],
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^sig-\\d{8}-[a-z0-9][a-z0-9-]*[a-z0-9]$",
      "description": "sig-YYYYMMDD-<slug>; must equal the filename stem."
    },
    "site_id": {
      "type": ["string", "null"],
      "description": "Ref: data/sites/<id>.yml. Null while the site is an unmatched candidate."
    },
    "site_hint": {
      "type": "string",
      "description": "Free-text site identification when site_id is null (name + county as reported)."
    },
    "attribute": {
      "type": "string",
      "pattern": "^[a-z0-9_.]+$",
      "description": "What the claim is about: status, capacity_mw, land_acres, investment_usd, operator, location, name, …"
    },
    "value": { "type": "string", "minLength": 1, "description": "The claim, raw, as reported — no normalization here." },
    "source_url": { "type": "string", "pattern": "^https?://" },
    "source_title": { "type": "string" },
    "publisher": { "type": "string" },
    "source_date": {
      "type": "string",
      "pattern": "^\\d{4}(-\\d{2}(-\\d{2})?)?$"
    },
    "observed_date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
    "collected_by": { "type": "string", "description": "Gnome name + run id, or console identifier." },
    "confidence": {
      "type": "string",
      "enum": ["low", "medium", "high"],
      "description": "Source-level trust for this single claim."
    },
    "notes": { "type": "string" }
  }
}
