@prefix owl:  <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .
@prefix dct:  <http://purl.org/dc/terms/> .
@prefix xeo:  <https://xeoontology.org/xeo#> .

# XEO — the ontology for the xEO family, core module.
# Namespace served from GitHub Pages; a w3id.org redirect may replace it later
# without changing term local names.

xeo: a owl:Ontology ;
    dct:title "XEO Core Ontology" ;
    dct:description "Standards-grounded observation layer for web-engine data in a property graph. XEO generalizes the xEO family (SEO, GEO, AEO): one vocabulary for how search, generative, and answer engines see and serve web content. Entities are durable, episodes are immutable, derivations carry provenance. Interpretations and decisions are modeled in higher layers." ;
    dct:creator "Inbound Found" ;
    owl:versionInfo "0.5.0" .

# --- Annotation properties -------------------------------------------------

xeo:epistemicLayer a owl:AnnotationProperty ;
    rdfs:comment "One of: entity, episode, observation, derivation, interpretation, norm. Types every term by the kind of claim it makes. Core terms stay at entity/episode/observation/derivation; extension modules may introduce interpretation- or norm-layer terms and must mark them." .

xeo:groundedIn a owl:AnnotationProperty ;
    rdfs:comment "The primary standard or API contract that defines this term's meaning." .

xeo:canonicalStore a owl:AnnotationProperty ;
    rdfs:comment "Where this term's instances authoritatively live: neo4j, bigquery, vector-store, crm. The ontology is storage-agnostic; identity keys (websiteId, address, term name, date) join across stores." .

# --- Classes ----------------------------------------------------------------

xeo:Website a owl:Class ;
    rdfs:label "Website" ;
    xeo:epistemicLayer "entity" ;
    xeo:groundedIn "WHATWG URL Standard (origin)" ;
    dct:description "A site under observation, identified by its origin. The tenancy scope for URLs, crawls, and topics." .

xeo:URL a owl:Class ;
    rdfs:label "URL" ;
    xeo:epistemicLayer "entity" ;
    xeo:groundedIn "WHATWG URL Standard" ;
    dct:description "A resource address within a Website. Durable identity; the state of the resource at a time is recorded by Fetch observations." .

xeo:Term a owl:Class ;
    rdfs:label "Term" ;
    xeo:epistemicLayer "entity" ;
    dct:description "A search query string, unique by name. Data sources are attributed on observations that mention the term, never as subtypes of the term." .

xeo:Crawl a owl:Class ;
    rdfs:label "Crawl" ;
    xeo:epistemicLayer "episode" ;
    dct:description "One crawl run over one Website: time-bounded, agent-attributed, immutable once finished." .

xeo:SerpSnapshot a owl:Class ;
    rdfs:label "SERP Snapshot" ;
    xeo:epistemicLayer "episode" ;
    dct:description "One observation of a search results page for a Term at a moment, for a stated engine, locale, and device." .

xeo:Topic a owl:Class ;
    rdfs:label "Topic" ;
    xeo:epistemicLayer "derivation" ;
    dct:description "A named grouping of Terms produced by a clustering or labeling process. Site-scoped. Assignments carry method, model, and confidence." .

xeo:SearchPerformanceFact a owl:Class ;
    rdfs:label "Search Performance Fact" ;
    xeo:epistemicLayer "observation" ;
    xeo:canonicalStore "bigquery" ;
    xeo:groundedIn "Google Search Console Search Analytics API" ;
    dct:description "The atomic ground-truth metric row for one (websiteId, address, term, date [, device, country]) tuple. Never instantiated as graph relationships; the graph carries windowed ranksFor rollups whose datasetUri points back to the authoritative table." .

# --- Object properties -------------------------------------------------------

xeo:partOf a owl:ObjectProperty ;
    rdfs:domain xeo:URL ; rdfs:range xeo:Website ;
    xeo:epistemicLayer "entity" .

xeo:hasCrawl a owl:ObjectProperty ;
    rdfs:domain xeo:Website ; rdfs:range xeo:Crawl ;
    xeo:epistemicLayer "episode" .

xeo:fetched a owl:ObjectProperty ;
    rdfs:domain xeo:Crawl ; rdfs:range xeo:URL ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "RFC 9110 (HTTP Semantics)" ;
    dct:description "An HTTP fetch of a URL within a crawl. In the property graph this relationship carries statusCode, contentType, title, metaDescription, robotsMeta, contentHash, fetchedAt." .

xeo:linksTo a owl:ObjectProperty ;
    rdfs:domain xeo:URL ; rdfs:range xeo:URL ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "WHATWG HTML §4.5.1 (the a element)" ;
    dct:description "An observed hyperlink. Carries anchorText, rel, firstSeenAt, lastSeenAt, lastSeenCrawlId." .

xeo:redirectsTo a owl:ObjectProperty ;
    rdfs:domain xeo:URL ; rdfs:range xeo:URL ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "RFC 9110 §15.4 (Redirection 3xx)" .

xeo:hasCanonical a owl:ObjectProperty ;
    rdfs:domain xeo:URL ; rdfs:range xeo:URL ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "RFC 6596 (The Canonical Link Relation)" .

xeo:ranksFor a owl:ObjectProperty ;
    rdfs:domain xeo:URL ; rdfs:range xeo:Term ;
    xeo:epistemicLayer "observation" ;
    xeo:canonicalStore "neo4j" ;
    xeo:groundedIn "Google Search Console Search Analytics API" ;
    dct:description "Windowed rollup projection of SearchPerformanceFacts for a (page, query) pair. Carries clicks, impressions, ctr, avgPosition, periodStart, periodEnd, source, datasetUri, syncedAt." .

xeo:hasSnapshot a owl:ObjectProperty ;
    rdfs:domain xeo:Term ; rdfs:range xeo:SerpSnapshot ;
    xeo:epistemicLayer "episode" .

xeo:hasResult a owl:ObjectProperty ;
    rdfs:domain xeo:SerpSnapshot ; rdfs:range xeo:URL ;
    xeo:epistemicLayer "observation" ;
    dct:description "A result observed on the SERP. Carries position and resultType." .

xeo:inTopic a owl:ObjectProperty ;
    rdfs:domain xeo:Term ; rdfs:range xeo:Topic ;
    xeo:epistemicLayer "derivation" ;
    dct:description "Process-attributed topic assignment. Carries method, model, confidence, assignedAt." .

xeo:childOf a owl:ObjectProperty ;
    rdfs:domain xeo:Topic ; rdfs:range xeo:Topic ;
    xeo:epistemicLayer "derivation" .

xeo:scopedTo a owl:ObjectProperty ;
    rdfs:domain xeo:Topic ; rdfs:range xeo:Website ;
    xeo:epistemicLayer "entity" .

# --- Datatype properties (selection; relationship-carried ones documented in README) ---

xeo:origin a owl:DatatypeProperty ;
    rdfs:domain xeo:Website ; rdfs:range xsd:string ;
    xeo:groundedIn "WHATWG URL Standard (origin serialization)" .

xeo:address a owl:DatatypeProperty ;
    rdfs:domain xeo:URL ; rdfs:range xsd:string ;
    xeo:groundedIn "WHATWG URL Standard (serialized absolute URL)" .

xeo:statusCode a owl:DatatypeProperty ;
    rdfs:range xsd:integer ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "RFC 9110 §15 (Status Codes)" .

xeo:anchorText a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "WHATWG HTML §4.5.1" .

xeo:clicks a owl:DatatypeProperty ;
    rdfs:range xsd:integer ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "GSC Search Analytics API" .

xeo:impressions a owl:DatatypeProperty ;
    rdfs:range xsd:integer ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "GSC Search Analytics API" .

xeo:avgPosition a owl:DatatypeProperty ;
    rdfs:range xsd:decimal ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "GSC Search Analytics API" .

xeo:embeddingRef a owl:DatatypeProperty ;
    rdfs:domain xeo:Term ; rdfs:range xsd:string ;
    xeo:epistemicLayer "derivation" ;
    xeo:canonicalStore "vector-store" ;
    dct:description "Pointer (collection + id) to the vector in the external store. The geometry lives where ANN search happens; the graph keeps the claim and its provenance." .

xeo:embeddingModel a owl:DatatypeProperty ;
    rdfs:domain xeo:Term ; rdfs:range xsd:string ;
    xeo:epistemicLayer "derivation" .

xeo:confidence a owl:DatatypeProperty ;
    rdfs:range xsd:decimal ;
    xeo:epistemicLayer "derivation" ;
    dct:description "0-1 confidence attached to a derivation edge." .

# --- Relationship-carried properties -----------------------------------------
# These ride on edges rather than nodes, so they carry no rdfs:domain. They were
# previously described in the README only, while context.jsonld already published
# them as xeo: IRIs — so they had to resolve. Declared here to close that gap.

xeo:websiteId a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "entity" ;
    dct:description "The tenancy key. Scope lives in this property on every scoped node and edge, never in a dynamic label — the identity half of 'tenancy is data, not schema'." .

xeo:datasetUri a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "derivation" ;
    dct:description "Pointer to the authoritative table a windowed rollup was projected from (e.g. a BigQuery table URI). The provenance contract for ranksFor and visibilityFor: the graph keeps the traversable projection, this says where the ground truth lives." .

xeo:name a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "entity" ;
    dct:description "The identifying name of a Term, Topic, Brand, or Capability. Unique within its scope; see schema.cypher for the per-class identity keys." .

xeo:title a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "WHATWG HTML (the title element)" ;
    dct:description "The document title observed on a fetch. Carried on the fetched edge, not on the URL: the address is durable, the title is what one crawl saw." .

xeo:metaDescription a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "WHATWG HTML (meta name=description)" ;
    dct:description "The meta description observed on a fetch. Carried on the fetched edge." .

xeo:rel a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "WHATWG HTML (link types)" ;
    dct:description "The rel attribute of an observed hyperlink (nofollow, sponsored, ugc, ...). Carried on linksTo." .

xeo:resultType a owl:DatatypeProperty ;
    rdfs:range xsd:string ;
    xeo:epistemicLayer "observation" ;
    dct:description "The kind of SERP result observed (organic, featured snippet, local pack, ...). Carried on hasResult; the vocabulary is per-engine and belongs to the consumer." .

xeo:position a owl:DatatypeProperty ;
    rdfs:range xsd:integer ;
    xeo:epistemicLayer "observation" ;
    dct:description "1-based rank of a result within a SERP snapshot. Carried on hasResult. Distinct from avgPosition, which is a windowed rollup, not a single observation." .

xeo:ctr a owl:DatatypeProperty ;
    rdfs:range xsd:decimal ;
    xeo:epistemicLayer "observation" ;
    xeo:groundedIn "GSC Search Analytics API" ;
    dct:description "Clickthrough rate over the rollup window. Carried on ranksFor." .

xeo:periodStart a owl:DatatypeProperty ;
    rdfs:range xsd:date ;
    xeo:epistemicLayer "derivation" ;
    dct:description "Inclusive first day of a rollup window. Carried on ranksFor and visibilityFor; never pool across windows silently." .

xeo:periodEnd a owl:DatatypeProperty ;
    rdfs:range xsd:date ;
    xeo:epistemicLayer "derivation" ;
    dct:description "Inclusive last day of a rollup window. Carried on ranksFor and visibilityFor." .

xeo:fetchedAt a owl:DatatypeProperty ;
    rdfs:range xsd:dateTime ;
    xeo:epistemicLayer "observation" ;
    dct:description "When the fetch observation was made. Carried on fetched." .

xeo:firstSeenAt a owl:DatatypeProperty ;
    rdfs:range xsd:dateTime ;
    xeo:epistemicLayer "observation" ;
    dct:description "When an observed edge (a link, typically) was first seen. Half of the bitemporal pair that makes link liveness answerable." .

xeo:lastSeenAt a owl:DatatypeProperty ;
    rdfs:range xsd:dateTime ;
    xeo:epistemicLayer "observation" ;
    dct:description "When an observed edge was most recently seen. With lastSeenCrawlId this is how a link is known to be live rather than merely once-observed." .

xeo:assignedAt a owl:DatatypeProperty ;
    rdfs:range xsd:dateTime ;
    xeo:epistemicLayer "derivation" ;
    dct:description "When a derivation edge was written (e.g. a topic assignment). Carried on inTopic alongside method, model and confidence." .

# --- Module IRI convention ---------------------------------------------------
# `xeo:` above names the ontology as a whole — all modules share one hash
# namespace, so a term IRI never says which file it came from. Each module also
# declares `xeo:<name>-module` (xeo:visibility-module, xeo:align-module, ...) so
# it can be versioned and cited on its own.
