{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://timefully.co/open-sit/schema/1.0.json",
  "title": "Open Sit 1.0",
  "description": "An open, file-based interchange format for meditation session history. CC0 1.0.",
  "type": "object",
  "required": ["opensit", "exported_at", "generator", "sessions"],
  "properties": {
    "$schema": { "type": "string", "format": "uri" },
    "opensit": {
      "type": "string",
      "pattern": "^1\\.[0-9]+$",
      "description": "Format version MAJOR.MINOR. This schema describes 1.x."
    },
    "exported_at": { "type": "string", "format": "date-time" },
    "generator": {
      "type": "object",
      "required": ["name"],
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "version": { "type": "string" }
      }
    },
    "sessions": {
      "type": "array",
      "items": { "$ref": "#/$defs/session" }
    },
    "extra": { "type": "object" }
  },
  "$defs": {
    "session": {
      "type": "object",
      "required": ["id", "started_at", "duration_seconds", "source"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "started_at": {
          "type": "string",
          "format": "date-time",
          "description": "RFC 3339 with UTC offset."
        },
        "timezone": {
          "type": "string",
          "minLength": 1,
          "description": "IANA zone id, e.g. Europe/Stockholm. Omit when unknown."
        },
        "duration_seconds": {
          "type": "number",
          "minimum": 1,
          "description": "Total timed duration including warm-up and cool-down."
        },
        "segments": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/segment" },
          "description": "Must sum to duration_seconds when present."
        },
        "title": { "type": "string" },
        "note": { "type": "string" },
        "method": {
          "type": "string",
          "description": "Open string. Documented: meditation, yoga, breathwork, walking, body_scan."
        },
        "mood": { "$ref": "#/$defs/mood" },
        "health": { "$ref": "#/$defs/health" },
        "source": { "$ref": "#/$defs/source" },
        "extra": { "type": "object" }
      }
    },
    "segment": {
      "type": "object",
      "required": ["kind", "duration_seconds"],
      "properties": {
        "kind": {
          "type": "string",
          "minLength": 1,
          "description": "Documented: warmup, main, cooldown. Readers fold unknown kinds into main."
        },
        "duration_seconds": { "type": "number", "minimum": 0 }
      }
    },
    "mood": {
      "type": "object",
      "required": ["label"],
      "properties": {
        "label": { "type": "string", "pattern": "^[a-z0-9_]+$" },
        "intensity": { "type": "number", "minimum": 0, "maximum": 1 },
        "valence": { "type": "number", "minimum": -1, "maximum": 1 },
        "arousal": { "type": "number", "minimum": -1, "maximum": 1 }
      }
    },
    "health": {
      "type": "object",
      "properties": {
        "average_hr_bpm": { "type": "number", "exclusiveMinimum": 0 },
        "average_hrv_sdnn_ms": { "type": "number", "exclusiveMinimum": 0 },
        "source_device": { "type": "string" }
      }
    },
    "source": {
      "type": "object",
      "required": ["name"],
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "id": { "type": "string", "minLength": 1 },
        "via": {
          "type": "string",
          "minLength": 1,
          "description": "Documented: apple_health, health_connect."
        }
      }
    }
  }
}
