{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://fullsend.ai/normative/entity-context-snapshot/v1/index.schema.json",
  "title": "EntityContextSnapshotIndex",
  "type": "object",
  "required": ["schema_version", "filter_version", "collection_profile", "filter", "source", "entity", "files", "records", "gaps"],
  "properties": {
    "schema_version": { "const": 1 },
    "filter_version": { "type": "string", "minLength": 1 },
    "collection_profile": { "$ref": "common.schema.json#/$defs/record_key" },
    "filter": {
      "allOf": [
        { "$ref": "#/$defs/filter" },
        { "properties": { "status": { "enum": ["unchanged", "modified", "truncated"] } } }
      ]
    },
    "source": {
      "type": "object",
      "required": ["forge", "host", "repository_id", "repository"],
      "properties": {
        "forge": { "enum": ["github", "gitlab", "forgejo"] },
        "host": {
          "type": "string",
          "pattern": "^[a-z0-9.-]+(:([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$",
          "allOf": [{ "not": { "pattern": ":443$" } }]
        },
        "repository_id": { "$ref": "common.schema.json#/$defs/structural_id" },
        "repository": {
          "allOf": [
            { "$ref": "common.schema.json#/$defs/repository_path" },
            { "pattern": "^[^/]+(/[^/]+)+$" }
          ]
        }
      },
      "allOf": [
        {
          "if": { "properties": { "forge": { "const": "github" } }, "required": ["forge"] },
          "then": {
            "properties": {
              "repository_id": { "$ref": "common.schema.json#/$defs/github_node_id" },
              "repository": { "pattern": "^[a-z0-9_.-]+/[a-z0-9_.-]+$" }
            }
          }
        },
        {
          "if": { "properties": { "forge": { "enum": ["gitlab", "forgejo"] } }, "required": ["forge"] },
          "then": { "properties": { "repository_id": { "pattern": "^[1-9][0-9]*$" } } }
        },
        {
          "if": { "properties": { "forge": { "const": "forgejo" } }, "required": ["forge"] },
          "then": { "properties": { "repository": { "pattern": "^[a-z0-9_.-]+/[a-z0-9_.-]+$" } } }
        }
      ],
      "additionalProperties": false
    },
    "entity": {
      "type": "object",
      "required": ["kind", "id"],
      "properties": {
        "kind": { "enum": ["work_item", "change_proposal"] },
        "id": {
          "$ref": "common.schema.json#/$defs/structural_id",
          "description": "Immutable opaque forge object ID; distinct from the positive display number in normalized-event v1 entity.id."
        },
        "updated_at": { "$ref": "common.schema.json#/$defs/timestamp" }
      },
      "additionalProperties": false
    },
    "files": {
      "type": "array",
      "items": { "$ref": "#/$defs/file" }
    },
    "records": {
      "type": "array",
      "items": { "$ref": "#/$defs/record" }
    },
    "gaps": {
      "type": "array",
      "items": { "$ref": "#/$defs/gap" },
      "description": "At most one row per (scope, code) pair; producers aggregate counts before canonical serialization and sort by scope then code."
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "source": {
            "properties": { "forge": { "const": "github" } },
            "required": ["forge"]
          }
        },
        "required": ["source"]
      },
      "then": {
        "properties": {
          "source": {
            "properties": {
              "repository_id": { "$ref": "common.schema.json#/$defs/github_node_id" }
            }
          },
          "entity": {
            "properties": {
              "id": { "$ref": "common.schema.json#/$defs/github_node_id" }
            }
          },
          "records": {
            "items": {
              "properties": {
                "id": { "$ref": "common.schema.json#/$defs/github_node_id" },
                "author_id": {
                  "oneOf": [
                    { "$ref": "common.schema.json#/$defs/github_node_id" },
                    { "type": "null" }
                  ]
                }
              }
            }
          }
        }
      }
    }
  ],
  "additionalProperties": false,
  "$defs": {
    "filter": {
      "type": "object",
      "required": ["status", "findings"],
      "properties": {
        "status": { "enum": ["unchanged", "modified", "truncated", "rejected"] },
        "findings": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["code", "count"],
            "properties": {
              "code": { "$ref": "common.schema.json#/$defs/finding_code" },
              "count": { "type": "integer", "minimum": 1 }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    },
    "file": {
      "type": "object",
      "required": ["path", "role", "media_type", "bytes", "sha256"],
      "properties": {
        "path": {
          "type": "string",
          "pattern": "^(collection[.]json|entity/metadata[.]json|records/([0-9]{8}T[0-9]{15}Z)-[0-9a-f]{64}[.]md|threads/[0-9a-f]{64}[.]order|views/(timeline|unresolved-review)[.]order|views/reviews/[0-9a-f]{64}[.]order|relations/reviews[.]json|history/agent-runs[.]json|checks/[0-9a-f]{64}/(metadata[.]json|log[.]txt)|state/(actors|threads)[.]json)$"
        },
        "role": {
          "enum": ["collection", "entity_metadata", "entity_record", "comment_record", "review_record", "thread_order", "timeline_view", "unresolved_review_view", "review_view", "reviews", "agent_runs", "check_metadata", "check_log", "actor_state", "thread_state"]
        },
        "media_type": {
          "enum": ["application/json", "text/markdown", "text/plain"]
        },
        "bytes": { "type": "integer", "minimum": 0 },
        "sha256": { "$ref": "common.schema.json#/$defs/record_key" },
        "filter": {
          "allOf": [
            { "$ref": "#/$defs/filter" },
            { "properties": { "status": { "enum": ["unchanged", "modified", "truncated"] } } }
          ]
        }
      },
      "allOf": [
        {
          "if": { "properties": { "role": { "enum": ["collection", "entity_metadata", "reviews", "agent_runs", "check_metadata", "actor_state", "thread_state"] } }, "required": ["role"] },
          "then": { "properties": { "media_type": { "const": "application/json" } } }
        },
        {
          "if": { "properties": { "role": { "enum": ["entity_record", "comment_record", "review_record"] } }, "required": ["role"] },
          "then": { "properties": { "media_type": { "const": "text/markdown" } } }
        },
        {
          "if": { "properties": { "role": { "enum": ["thread_order", "timeline_view", "unresolved_review_view", "review_view", "check_log"] } }, "required": ["role"] },
          "then": { "properties": { "media_type": { "const": "text/plain" } } }
        },
        {
          "if": { "properties": { "role": { "enum": ["entity_metadata", "reviews", "agent_runs", "check_metadata", "check_log", "actor_state"] } }, "required": ["role"] },
          "then": { "required": ["filter"] }
        }
      ],
      "additionalProperties": false
    },
    "gap": {
      "type": "object",
      "required": ["scope", "code", "usability", "count"],
      "properties": {
        "scope": { "enum": ["entity", "comments", "reviews", "checks", "check_logs", "agent_runs", "actors"] },
        "code": { "enum": ["profile_bound", "history_unavailable", "unsupported", "authorization_failed", "fetch_failed", "source_too_large", "invalid_metadata", "unsafe_content"] },
        "usability": { "enum": ["partial", "unusable"] },
        "count": { "type": "integer", "minimum": 1 }
      },
      "allOf": [
        {
          "if": { "properties": { "code": { "enum": ["profile_bound", "history_unavailable"] } }, "required": ["code"] },
          "then": { "properties": { "usability": { "const": "partial" } } },
          "else": { "properties": { "usability": { "const": "unusable" } } }
        }
      ],
      "additionalProperties": false
    },
    "record": {
      "type": "object",
      "required": ["kind", "id", "record_key", "created_at", "filter"],
      "properties": {
        "kind": { "enum": ["entity", "comment", "review", "check"] },
        "id": { "$ref": "common.schema.json#/$defs/structural_id" },
        "record_key": { "$ref": "common.schema.json#/$defs/record_key" },
        "content_path": { "type": "string", "pattern": "^records/[0-9]{8}T[0-9]{15}Z-[0-9a-f]{64}[.]md$" },
        "metadata_path": { "type": "string", "pattern": "^checks/[0-9a-f]{64}/metadata[.]json$" },
        "log_path": { "type": "string", "pattern": "^checks/[0-9a-f]{64}/log[.]txt$" },
        "author_id": {
          "oneOf": [
            { "$ref": "common.schema.json#/$defs/structural_id" },
            { "type": "null" }
          ]
        },
        "author": { "type": ["string", "null"], "minLength": 1 },
        "created_at": { "$ref": "common.schema.json#/$defs/timestamp" },
        "updated_at": { "$ref": "common.schema.json#/$defs/timestamp" },
        "filter": { "$ref": "#/$defs/filter" }
      },
      "allOf": [
        {
          "if": { "properties": { "kind": { "const": "check" } }, "required": ["kind"] },
          "then": { "not": { "anyOf": [{ "required": ["author_id"] }, { "required": ["author"] }] } },
          "else": { "required": ["author_id", "author"] }
        },
        {
          "if": { "properties": { "filter": { "properties": { "status": { "const": "rejected" } } } } },
          "then": { "not": { "anyOf": [{ "required": ["content_path"] }, { "required": ["metadata_path"] }, { "required": ["log_path"] }] } },
          "else": {
            "if": { "properties": { "kind": { "const": "check" } } },
            "then": {
              "required": ["metadata_path"],
              "not": { "required": ["content_path"] }
            },
            "else": {
              "required": ["content_path"],
              "not": { "anyOf": [{ "required": ["metadata_path"] }, { "required": ["log_path"] }] }
            }
          }
        }
      ],
      "additionalProperties": false
    }
  }
}
