{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://newruntime.com/crawler-journeys-schema.json",
  "title": "New Runtime crawler journey aggregate v1",
  "description": "Privacy-safe per-family crawl depth and observed transition aggregates. No IP, hostname, session identifier, raw User-Agent, or raw path session is serialized.",
  "type": "object",
  "required": [
    "schema_version",
    "contract_version",
    "type",
    "generated_at",
    "source_window",
    "sessionization",
    "journey_windows",
    "privacy",
    "interpretation"
  ],
  "properties": {
    "schema_version": {
      "const": 1
    },
    "contract_version": {
      "const": "newruntime-crawler-journeys-v1"
    },
    "type": {
      "const": "crawler_journey_aggregate"
    },
    "stable_id": {
      "type": "string"
    },
    "generated_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "refresh_hint": {
      "type": "string"
    },
    "human_url": {
      "type": "string",
      "format": "uri"
    },
    "schema_url": {
      "type": "string",
      "format": "uri"
    },
    "source_window": {
      "$ref": "#/$defs/sourceWindow"
    },
    "sessionization": {
      "type": "object",
      "required": [
        "gap_seconds",
        "subject",
        "canonicalization",
        "path_semantics"
      ],
      "properties": {
        "gap_seconds": {
          "type": "integer",
          "minimum": 60
        },
        "subject": {
          "type": "string"
        },
        "canonicalization": {
          "type": "string"
        },
        "path_semantics": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "identity_confidence": {
      "type": "object"
    },
    "verification_counts": {
      "type": "object"
    },
    "eligible_canonical_nodes": {
      "type": "integer",
      "minimum": 0
    },
    "families": {
      "type": "array"
    },
    "observed_sequences": {
      "type": "object"
    },
    "discovery_latency": {
      "type": "object"
    },
    "window_metrics": {
      "type": "array"
    },
    "journey_windows": {
      "type": "array",
      "minItems": 3,
      "items": {
        "$ref": "#/$defs/journeyWindow"
      }
    },
    "graph_observation": {
      "type": [
        "object",
        "null"
      ]
    },
    "verification_sources": {
      "type": "array"
    },
    "privacy": {
      "type": "object"
    },
    "interpretation": {
      "type": "object"
    }
  },
  "additionalProperties": true,
  "$defs": {
    "sourceWindow": {
      "type": "object",
      "required": [
        "first_seen",
        "last_seen"
      ],
      "properties": {
        "first_seen": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "last_seen": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "additionalProperties": false
    },
    "countPath": {
      "type": "object",
      "required": [
        "path",
        "count"
      ],
      "properties": {
        "path": {
          "type": "string",
          "pattern": "^/"
        },
        "count": {
          "type": "integer",
          "minimum": 0
        }
      },
      "additionalProperties": false
    },
    "transition": {
      "type": "object",
      "required": [
        "from",
        "to",
        "count"
      ],
      "properties": {
        "from": {
          "type": "string",
          "pattern": "^/"
        },
        "to": {
          "type": "string",
          "pattern": "^/"
        },
        "count": {
          "type": "integer",
          "minimum": 0
        }
      },
      "additionalProperties": false
    },
    "familyJourney": {
      "type": "object",
      "required": [
        "family",
        "verification_status",
        "sessions",
        "material_reads",
        "unique_materials",
        "median_materials_per_session",
        "max_materials_per_session",
        "top_transitions",
        "top_path_patterns"
      ],
      "properties": {
        "family": {
          "type": "string"
        },
        "verification_status": {
          "enum": [
            "verified",
            "claimed_unverified",
            "not_verifiable"
          ]
        },
        "verification_method": {
          "type": "string"
        },
        "sessions": {
          "type": "integer",
          "minimum": 0
        },
        "successful_sessions": {
          "type": "integer",
          "minimum": 0
        },
        "requests": {
          "type": "integer",
          "minimum": 0
        },
        "successful_requests": {
          "type": "integer",
          "minimum": 0
        },
        "canonical_node_reads": {
          "type": "integer",
          "minimum": 0
        },
        "material_reads": {
          "type": "integer",
          "minimum": 0
        },
        "unique_canonical_nodes": {
          "type": "integer",
          "minimum": 0
        },
        "unique_materials": {
          "type": "integer",
          "minimum": 0
        },
        "median_canonical_nodes_per_session": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "p95_canonical_nodes_per_session": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "max_canonical_nodes_per_session": {
          "type": "integer",
          "minimum": 0
        },
        "median_materials_per_session": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "p95_materials_per_session": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "max_materials_per_session": {
          "type": "integer",
          "minimum": 0
        },
        "median_transitions_per_session": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "max_transitions_per_session": {
          "type": "integer",
          "minimum": 0
        },
        "max_entrypoint_distance": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "manifest_sessions": {
          "type": "integer",
          "minimum": 0
        },
        "manifest_followthrough_sessions": {
          "type": "integer",
          "minimum": 0
        },
        "followthrough_percent": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 100
        },
        "entrypoints": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/countPath"
          }
        },
        "terminal_routes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/countPath"
          }
        },
        "top_transitions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/transition"
          }
        },
        "top_path_patterns": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "pattern",
              "count"
            ],
            "properties": {
              "pattern": {
                "type": "string"
              },
              "count": {
                "type": "integer",
                "minimum": 0
              }
            },
            "additionalProperties": false
          }
        },
        "formats": {
          "type": "array"
        },
        "first_seen": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "last_seen": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        }
      },
      "additionalProperties": false
    },
    "journeyWindow": {
      "type": "object",
      "required": [
        "window",
        "source_window",
        "session_gap_seconds",
        "families"
      ],
      "properties": {
        "window": {
          "enum": [
            "24h",
            "7d",
            "30d"
          ]
        },
        "source_window": {
          "$ref": "#/$defs/sourceWindow"
        },
        "session_gap_seconds": {
          "type": "integer",
          "minimum": 60
        },
        "families": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/familyJourney"
          }
        }
      },
      "additionalProperties": false
    }
  }
}
