{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "schema_version": {
      "const": 1
    },
    "dot_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40,
      "pattern": "^[^\\x00-\\x1F\\x7F]+$"
    },
    "period": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "from": {
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "through": {
          "type": "string",
          "format": "date",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "timezone": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        }
      },
      "required": [
        "from",
        "through",
        "timezone"
      ]
    },
    "days": {
      "type": "array",
      "minItems": 1,
      "maxItems": 3660,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "completed": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 10000000
              },
              {
                "type": "null"
              }
            ]
          },
          "coverage": {
            "enum": [
              "complete",
              "partial",
              "unknown"
            ]
          }
        },
        "required": [
          "date",
          "completed",
          "coverage"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "coverage": {
                  "const": "unknown"
                }
              }
            },
            "then": {
              "properties": {
                "completed": {
                  "type": "null"
                }
              }
            },
            "else": {
              "properties": {
                "completed": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 10000000
                }
              }
            }
          },
          {
            "if": {
              "properties": {
                "coverage": {
                  "const": "partial"
                }
              }
            },
            "then": {
              "properties": {
                "completed": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 10000000
                }
              }
            }
          }
        ]
      }
    },
    "environments": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "user_computer": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "dot_cloud": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "mixed": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "other": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "unknown": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        }
      },
      "required": [
        "user_computer",
        "dot_cloud",
        "mixed",
        "other",
        "unknown"
      ]
    },
    "apps": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "observed_tasks": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "counts": {
          "type": "array",
          "minItems": 1,
          "maxItems": 11,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "app": {
                "enum": [
                  "browser",
                  "gmail",
                  "google_calendar",
                  "google_drive",
                  "slack",
                  "github",
                  "linear",
                  "notion",
                  "figma",
                  "canva",
                  "other"
                ]
              },
              "tasks": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000
              }
            },
            "required": [
              "app",
              "tasks"
            ]
          }
        }
      },
      "required": [
        "observed_tasks",
        "counts"
      ]
    },
    "contexts": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "work": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "personal": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "mixed": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        },
        "unclassified": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10000000
        }
      },
      "required": [
        "work",
        "personal",
        "mixed",
        "unclassified"
      ]
    },
    "conversations": {
      "type": "object",
      "additionalProperties": false,
      "description": "Messages from only the confirmed user-selected dot conversation after the routing check. This is not a completed-task metric. Optional history records exact bounded availability/cutoff timestamps, source counts, undated-message totals, and unresolved retrieval gaps; gaps never imply zero messages. Optional legacy per-day contexts are accepted for compatibility, validated against known message totals, and discarded from canonical output. Semantic validation also requires exact chronological coverage of the selected period, a total messages_sent sum no greater than 10000000, no future dates, and no complete coverage for today.",
      "properties": {
        "source": { "const": "dot_conversation" },
        "scope": { "const": "current_conversation" },
        "threads": {
          "type": ["integer", "null"],
          "enum": [1, null],
          "description": "Only the single current dot conversation; null is permitted when a selected-year export cannot attribute a period-level count. Never include other threads."
        },
        "days": {
          "type": "array",
          "minItems": 1,
          "maxItems": 3660,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
              },
              "messages_sent": {
                "anyOf": [
                  { "type": "integer", "minimum": 0, "maximum": 10000000 },
                  { "type": "null" }
                ]
              },
              "coverage": { "enum": ["complete", "partial", "unknown"] },
              "contexts": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "work": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                  "personal": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                  "unclassified": { "type": "integer", "minimum": 0, "maximum": 10000000 }
                },
                "required": ["work", "personal", "unclassified"]
              }
            },
            "required": ["date", "messages_sent", "coverage"],
            "allOf": [
              {
                "if": {
                  "properties": { "coverage": { "const": "unknown" } },
                  "required": ["coverage"]
                },
                "then": {
                  "properties": { "messages_sent": { "type": "null" } },
                  "not": { "required": ["contexts"] }
                },
                "else": {
                  "properties": {
                    "messages_sent": { "type": "integer", "minimum": 0, "maximum": 10000000 }
                  }
                }
              },
              {
                "if": {
                  "properties": { "coverage": { "const": "partial" } },
                  "required": ["coverage"]
                },
                "then": {
                  "properties": {
                    "messages_sent": { "type": "integer", "minimum": 1, "maximum": 10000000 }
                  }
                }
              }
            ]
          }
        },
        "history": {
          "type": "object",
          "additionalProperties": false,
          "description": "Optional source-bound coverage metadata. available_from and analyzed_through are canonical UTC timestamps whose local dates in period.timezone must be inside the selected period. source_counts, when present, uses only chatgpt, codex, mirrored_slack, text, and other; its sum equals the known dated messages_sent total, excluding undated_messages. gaps are unresolved retrieval windows, never evidence of zero messages. Semantic validation requires ordered, nonoverlapping gaps within the availability range, at least one partial or unknown day when gaps exist, no complete day overlapping a gap, and no complete archetype over gaps.",
          "properties": {
            "available_from": {
              "type": "string",
              "format": "date-time",
              "minLength": 20,
              "maxLength": 24,
              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$"
            },
            "analyzed_through": {
              "type": "string",
              "format": "date-time",
              "minLength": 20,
              "maxLength": 24,
              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$"
            },
            "source_counts": {
              "type": "object",
              "description": "Count each dated owner message once by verified original channel within this conversation. Text is iMessage or RCS. Omit unavailable channels; zero requires evidence. Other includes unattributed messages.",
              "minProperties": 1,
              "additionalProperties": false,
              "properties": {
                "chatgpt": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                "codex": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                "mirrored_slack": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                "text": { "type": "integer", "minimum": 0, "maximum": 10000000 },
                "other": { "type": "integer", "minimum": 0, "maximum": 10000000 }
              }
            },
            "undated_messages": { "type": "integer", "minimum": 0, "maximum": 10000000 },
            "gaps": {
              "type": "array",
              "maxItems": 64,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "from": {
                    "type": "string",
                    "format": "date-time",
                    "minLength": 20,
                    "maxLength": 24,
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$"
                  },
                  "through": {
                    "type": "string",
                    "format": "date-time",
                    "minLength": 20,
                    "maxLength": 24,
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$"
                  }
                },
                "required": ["from", "through"]
              }
            }
          },
          "required": ["available_from", "analyzed_through", "undated_messages", "gaps"]
        },
        "voice": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "calls": {
              "anyOf": [
                { "type": "integer", "minimum": 0, "maximum": 10000000 },
                { "type": "null" }
              ]
            },
            "seconds": {
              "anyOf": [
                { "type": "integer", "minimum": 0, "maximum": 316224000 },
                { "type": "null" }
              ]
            },
            "coverage": { "enum": ["complete", "partial"] }
          },
          "required": ["calls", "seconds", "coverage"],
          "allOf": [
            {
              "not": {
                "properties": {
                  "calls": { "type": "null" },
                  "seconds": { "type": "null" }
                },
                "required": ["calls", "seconds"]
              }
            },
            {
              "if": {
                "properties": {
                  "coverage": { "const": "partial" },
                  "calls": { "const": 0 }
                },
                "required": ["coverage", "calls"]
              },
              "then": {
                "properties": { "seconds": { "type": "integer", "minimum": 1, "maximum": 316224000 } }
              }
            },
            {
              "if": {
                "properties": {
                  "coverage": { "const": "partial" },
                  "seconds": { "const": 0 }
                },
                "required": ["coverage", "seconds"]
              },
              "then": {
                "properties": { "calls": { "type": "integer", "minimum": 1, "maximum": 10000000 } }
              }
            }
          ]
        },
        "archetype": {
          "type": "object",
          "additionalProperties": false,
          "description": "An optional, playful agent inference about recurring chat habits; not a psychological test or diagnosis. Analyze recurring help-request patterns across the full available history of this exact conversation, then choose a single best fit. Use the dominant pattern and broader history to resolve close matches. Do not derive the choice from message volume, day counts, coverage counts, or work labels. Do not invent a personality diagnosis; omit the archetype when evidence is insufficient or the best fit is unclear. Never return raw reasons, topics, examples, or message extracts.\n- maker: builds usable artifacts and things\n- explorer: open-ended discovery and connecting ideas\n- planner: maps an already chosen direction into steps, schedules, and milestones; prefer strategist for choosing the direction, jetsetter for recurring travel, and organizer for routines and coordination\n- strategist: chooses big-picture direction by comparing alternatives, priorities, tradeoffs, and longer-term bets; prefer planner when the direction is already chosen and help focuses on executing it\n- scholar: learning and deep explanations\n- editor: rewriting, review, polish, and refinement\n- organizer: checklists, routines, coordination, and turning a mess into steps\n- jetsetter: destinations, itineraries, bookings, and travel logistics; a single trip mention is not a recurring travel pattern\n- alchemist (rare): repeatedly combines unrelated disciplines, tools, or ideas into new usable concepts or artifacts; use maker for straightforward building and explorer for discovery without recurring synthesis\n- wildcard (rare): repeatedly asks for playful experiments with unusual constraints, deliberate reversals, or unexpected formats; broad topic variety, uncertainty, or a one-off joke is not enough\nRare-match rule: alchemist and wildcard require at least three distinct owner help requests across at least two separately dated days in this exact conversation that clearly meet their specific pattern, with that pattern dominant in the available history. Do not count quoted examples, assistant suggestions, or repeated messages about the same request as separate evidence. Otherwise select the best supported standard archetype, or omit when unclear. Rare is a stricter match tier, not a measured population frequency. Never assign it randomly, force quotas, invent probabilities, or use wildcard as a fallback for an unclear match. Complete coverage requires every conversation day to be complete and no unresolved history gaps.",
          "properties": {
            "key": {
              "enum": ["maker","explorer","planner","strategist","scholar","editor","organizer","jetsetter","alchemist","wildcard"]
            },
            "coverage": { "enum": ["partial", "complete"] }
          },
          "required": ["key", "coverage"]
        }
      },
      "allOf": [
        {
          "if": {
            "required": ["archetype"],
            "properties": {
              "archetype": {
                "required": ["coverage"],
                "properties": { "coverage": { "const": "complete" } }
              }
            }
          },
          "then": {
            "properties": {
              "days": {
                "items": {
                  "required": ["coverage"],
                  "properties": { "coverage": { "const": "complete" } }
                }
              }
            }
          }
        },
        {
          "if": {
            "required": ["history"],
            "properties": {
              "history": {
                "required": ["gaps"],
                "properties": { "gaps": { "minItems": 1 } }
              }
            }
          },
          "then": {
            "properties": {
              "days": {
                "contains": {
                  "required": ["coverage"],
                  "properties": { "coverage": { "enum": ["partial", "unknown"] } }
                }
              }
            },
            "not": {
              "required": ["archetype"],
              "properties": {
                "archetype": {
                  "required": ["coverage"],
                  "properties": { "coverage": { "const": "complete" } }
                }
              }
            }
          }
        }
      ],
      "required": ["source", "scope", "threads", "days"]
    }
  },
  "required": [
    "schema_version",
    "dot_name",
    "period",
    "days"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Dot Profile aggregate snapshot v1",
  "description": "Strict owner-reported aggregate statistics. Legacy completed-task counts and optional local Codex conversation activity are separate families. Additional semantic validation of dates, timezone, sums, uniqueness, coverage, payload size, and profile name is required."
}
