UJG / UJG 1.0 Release Candidate 1 /
GitHub
Table of Contents
  • 1Overview
  • 2Terminology
  • 3ObservationEvent
  • 4InputModality
  • 5InputModalityProfile
  • 6AccessibleFeature
  • 7AccessibleRelation
  • 8AccessibleLocator
  • 9CustomLocator
  • 10SurfaceInstanceResolver
  • 11ObservationBinding
  • 12Binding Model
  • 13Locator Model
  • 14Runtime Correlation
  • 15Normative Artifacts
    • 15.1Ontology
    • 15.2JSON-LD Context
    • 15.3Validation
  • 16Examples
    • 16.1Minimal Example
    • 16.2Input Modality Requirement Example
    • 16.3Runtime Correlation Example
W3C Community Group Draft Report

Observability

draft

Status of this Document

This report was published by the User Journal Graph Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

Status
CG-DRAFT
Version
1.0-rc1
Published
2026-07-27
Last Update
2026-07-27
Editors
  • Seva Dolgopolov
Group
User Journal Graph Community Group
Repository
View Source
License
W3C-Software-and-Document

1. Overview

This second-level optional module defines a recognition contract for Surface nodes. It lets producers declare how a visible surface can be recognized by synthetic checks, browser collectors, native collectors, or other observation adapters without changing Graph traversal or Runtime ordering.

Observability depends on [UJG Surface] and [UJG Localization]. A binding points to a Surface and uses localized message bundles when accessible names or descriptions are part of recognition. Concrete runtime occurrence identity is derived by the collector when Runtime data is emitted. When a binding has a SurfaceInstanceResolver, the resolver identifies the accessibility-exposed feature used to derive the concrete instance key.

Observability has no direct dependency on Runtime. When Runtime data is present, a consumer can correlate events to bindings by resolving RuntimeEvent.surfaceInstanceRef to a SurfaceInstance and matching that instance's surfaceRef to ObservationBinding.observeSurfaceRef.

Observation events can also reference input-modality profiles. This lets a producer describe affordance recognition across independently evaluated input strategies while keeping the Graph transition model unchanged. Observability standardizes keyboard and pointer modality identifiers; other modality identifiers remain producer-defined.

2. Terminology

  • ObservationBinding: An addressable recognition contract for one Surface.

  • ObservationEvent: An addressable, owner-defined semantic event contract.

  • InputModality: An addressable input modality. observability:keyboard and observability:pointer are standard modalities; other concrete modality identifiers are producer-defined.

  • InputModalityProfile: An addressable interaction strategy defined by one or more input modalities.

  • AccessibleLocator: A locator that describes an accessible object using accessibility role, localized computed name or description references, state/property features, relations, and context.

  • AccessibleFeature: An accessibility state or property used by an accessible locator.

  • AccessibleRelation: A relationship between accessible objects used by an accessible locator.

  • CustomLocator: An opaque extension-backed locator for adapter-specific matching.

  • SurfaceInstanceResolver: A reusable resolver that identifies how an adapter derives a concrete SurfaceInstance key for repeated occurrences of the same stable Surface.

  • Collector: A runtime observation component that evaluates ObservationBinding nodes against an observed environment, resolves or creates the applicable SurfaceInstance when Runtime data is emitted, and records observed events without changing Graph, Surface, or Observability definitions.

  • Synthetic Runner: A collector that drives or inspects a journey through automated execution, such as a Playwright-based browser test. A synthetic runner may activate accessible objects, match locators, and emit Runtime events, but its automation commands are not modeled as Graph traversal rules or Observability vocabulary.

3. ObservationEvent

An ObservationEvent identifies the semantic event contract a binding observes. Event identifiers are producer-defined; this module does not reserve standard event IRIs.

An event can optionally reference one or more InputModalityProfiles.

classDiagram
  class InputModalityProfile
  class ObservationEvent {
    id
    requiredInputModalityProfileRefs
  }
  ObservationEvent --> "0..*" InputModalityProfile : requiredInputModalityProfileRefs

Example JSON nodes:

json
[
  {
    "@type": "ObservationEvent",
    "@id": "urn:observation-event:presence",
    "label": "Presence"
  },
  {
    "@type": "ObservationEvent",
    "@id": "urn:observation-event:activation",
    "label": "Activation",
    "requiredInputModalityProfileRefs": [
      "urn:ujg:input-modality-profile:keyboard"
    ]
  }
]
[
  {
    "@type": "ObservationEvent",
    "@id": "urn:observation-event:presence",
    "label": "Presence"
  },
  {
    "@type": "ObservationEvent",
    "@id": "urn:observation-event:activation",
    "label": "Activation",
    "requiredInputModalityProfileRefs": [
      "urn:ujg:input-modality-profile:keyboard"
    ]
  }
]

4. InputModality

An InputModality identifies one input modality that can participate in an interaction strategy. This module defines two standard input modality identifiers:

  • observability:keyboard: keyboard-based interaction.

  • observability:pointer: pointer-based interaction, including mouse, pen, touch, or equivalent pointing input.

Other concrete modality identifiers are producer-defined.

The standard modality identifiers are declared as InputModality resources by the normative Observability ontology. Producers MAY reference them without serializing duplicate InputModality nodes in a document.

classDiagram
  class InputModality {
    id
  }

Example JSON nodes:

json
[
  {
    "@id": "observability:keyboard",
    "@type": "InputModality"
  },
  {
    "@id": "observability:pointer",
    "@type": "InputModality"
  }
]
[
  {
    "@id": "observability:keyboard",
    "@type": "InputModality"
  },
  {
    "@id": "observability:pointer",
    "@type": "InputModality"
  }
]

5. InputModalityProfile

An InputModalityProfile identifies one independently evaluable interaction strategy. Its inputModalityRefs values identify the modalities that participate in that strategy.

classDiagram
  class InputModality
  class InputModalityProfile {
    id
    inputModalityRefs
  }
  InputModalityProfile --> "1..*" InputModality : inputModalityRefs

Example JSON node:

json
{
  "@type": "InputModalityProfile",
  "@id": "urn:ujg:input-modality-profile:keyboard",
  "label": "Keyboard",
  "inputModalityRefs": [
    "observability:keyboard"
  ]
}
{
  "@type": "InputModalityProfile",
  "@id": "urn:ujg:input-modality-profile:keyboard",
  "label": "Keyboard",
  "inputModalityRefs": [
    "observability:keyboard"
  ]
}

6. AccessibleFeature

An AccessibleFeature describes an accessibility state or property used by an AccessibleLocator or SurfaceInstanceResolver.

classDiagram
  class AccessibleFeature {
    id
    accessibleFeatureName
    accessibleFeatureValue
  }

Example JSON node:

json
{
  "@type": "AccessibleFeature",
  "@id": "urn:ujg:accessible-feature:selected-true",
  "accessibleFeatureName": "selected",
  "accessibleFeatureValue": "true"
}
{
  "@type": "AccessibleFeature",
  "@id": "urn:ujg:accessible-feature:selected-true",
  "accessibleFeatureName": "selected",
  "accessibleFeatureValue": "true"
}

7. AccessibleRelation

An AccessibleRelation describes a relationship between accessible objects used by an AccessibleLocator.

classDiagram
  class AccessibleLocator
  class AccessibleRelation {
    id
    accessibleRelationType
    targetLocatorRef
  }
  AccessibleRelation --> AccessibleLocator : targetLocatorRef

Example JSON node:

json
{
  "@type": "AccessibleRelation",
  "@id": "urn:ujg:accessible-relation:form-labelled-by-heading",
  "accessibleRelationType": "labelled-by",
  "targetLocatorRef": "urn:ujg:locator:checkout-heading"
}
{
  "@type": "AccessibleRelation",
  "@id": "urn:ujg:accessible-relation:form-labelled-by-heading",
  "accessibleRelationType": "labelled-by",
  "targetLocatorRef": "urn:ujg:locator:checkout-heading"
}

8. AccessibleLocator

An AccessibleLocator describes an accessible object through role, localized name or description references, accessibility features, relations, and optional context locators.

classDiagram
  class MessageMeta
  class AccessibleFeature
  class AccessibleRelation
  class AccessibleLocator {
    id
    role
    accessibleNameRef
    accessibleDescriptionRef
    accessibleFeatureRefs
    accessibleRelationRefs
    contextLocatorRefs
  }
  AccessibleLocator --> MessageMeta : accessibleNameRef
  AccessibleLocator --> MessageMeta : accessibleDescriptionRef
  AccessibleLocator --> "0..*" AccessibleFeature : accessibleFeatureRefs
  AccessibleLocator --> "0..*" AccessibleRelation : accessibleRelationRefs
  AccessibleLocator --> "0..*" AccessibleLocator : contextLocatorRefs

Example JSON node:

json
{
  "@type": "AccessibleLocator",
  "@id": "urn:ujg:locator:checkout-submit",
  "role": "button",
  "accessibleNameRef": "urn:l10n:message-meta:submit-order"
}
{
  "@type": "AccessibleLocator",
  "@id": "urn:ujg:locator:checkout-submit",
  "role": "button",
  "accessibleNameRef": "urn:l10n:message-meta:submit-order"
}

9. CustomLocator

A CustomLocator is an opaque extension-backed locator for adapter-specific matching when interoperable accessible-object recognition is not enough.

classDiagram
  class CustomLocator {
    id
    extensions
  }

Example JSON node:

json
{
  "@type": "CustomLocator",
  "@id": "urn:ujg:locator:checkout-submit-test-id",
  "extensions": {
    "com.acme.locator": {
      "testId": "submit-order"
    }
  }
}
{
  "@type": "CustomLocator",
  "@id": "urn:ujg:locator:checkout-submit-test-id",
  "extensions": {
    "com.acme.locator": {
      "testId": "submit-order"
    }
  }
}

10. SurfaceInstanceResolver

A SurfaceInstanceResolver declares which accessible feature supplies the instance key for repeated concrete occurrences of the same stable Surface.

classDiagram
  class AccessibleFeature
  class SurfaceInstanceResolver {
    id
    instanceKeyFeatureRef
  }
  SurfaceInstanceResolver --> AccessibleFeature : instanceKeyFeatureRef

Example JSON node:

json
{
  "@type": "SurfaceInstanceResolver",
  "@id": "urn:ujg:resolver:cart-line-item",
  "instanceKeyFeatureRef": "urn:ujg:accessible-feature:line-item-sku"
}
{
  "@type": "SurfaceInstanceResolver",
  "@id": "urn:ujg:resolver:cart-line-item",
  "instanceKeyFeatureRef": "urn:ujg:accessible-feature:line-item-sku"
}

11. ObservationBinding

An ObservationBinding binds one Surface to one ObservationEvent and one or more locator nodes that define the recognition evidence.

classDiagram
  class Surface
  class ObservationEvent
  class AccessibleLocator
  class CustomLocator
  class SurfaceInstanceResolver
  class ObservationBinding {
    id
    observeSurfaceRef
    observationEventRef
    locatorRefs
    surfaceInstanceResolverRef
    expectedMatchCount
  }
  ObservationBinding --> Surface : observeSurfaceRef
  ObservationBinding --> ObservationEvent : observationEventRef
  ObservationBinding --> AccessibleLocator : locatorRefs
  ObservationBinding --> CustomLocator : locatorRefs
  ObservationBinding --> SurfaceInstanceResolver : surfaceInstanceResolverRef

Example JSON node:

json
{
  "@type": "ObservationBinding",
  "@id": "urn:ujg:observation-binding:checkout-submit-presence",
  "observeSurfaceRef": "urn:ujg:surface:checkout-submit",
  "observationEventRef": "urn:ujg:observation-event:presence",
  "locatorRefs": ["urn:ujg:locator:checkout-submit"]
}
{
  "@type": "ObservationBinding",
  "@id": "urn:ujg:observation-binding:checkout-submit-presence",
  "observeSurfaceRef": "urn:ujg:surface:checkout-submit",
  "observationEventRef": "urn:ujg:observation-event:presence",
  "locatorRefs": ["urn:ujg:locator:checkout-submit"]
}

Example absence assertion:

json
{
  "@type": "ObservationBinding",
  "@id": "urn:ujg:observation-binding:checkout-error-absent",
  "observeSurfaceRef": "urn:ujg:surface:checkout-error",
  "observationEventRef": "urn:ujg:observation-event:presence",
  "locatorRefs": ["urn:ujg:locator:checkout-error"],
  "expectedMatchCount": 0
}
{
  "@type": "ObservationBinding",
  "@id": "urn:ujg:observation-binding:checkout-error-absent",
  "observeSurfaceRef": "urn:ujg:surface:checkout-error",
  "observationEventRef": "urn:ujg:observation-event:presence",
  "locatorRefs": ["urn:ujg:locator:checkout-error"],
  "expectedMatchCount": 0
}

12. Binding Model

The module introduces one canonical interoperable attachment:

  • observability:observeSurfaceRef links an ObservationBinding to one Surface.

An ObservationBinding also identifies:

  • observationEventRef: the semantic event being observed.

  • locatorRefs: one or more locator nodes that define how the surface evidence is recognized.

  • surfaceInstanceResolverRef: an optional resolver for deriving a concrete SurfaceInstance when the same stable surface is repeated.

  • expectedMatchCount: an optional exact cardinality for the full conjunctive locator match.

locatorRefs inside one binding are conjunctive: all referenced locators must match. Alternative recognition strategies SHOULD be modeled as separate ObservationBinding nodes that reference the same surface.

When expectedMatchCount is present, a consumer that evaluates the binding MUST compare the number of objects matching the binding's full locatorRefs contract in the current recognition scope to that exact non-negative integer. expectedMatchCount: 0 means the locator contract is expected to find no matching objects. expectedMatchCount: 1 means exactly one matching object is expected. If expectedMatchCount is omitted, the binding preserves the existing positive recognition semantics without exact cardinality.

One ObservationBinding can describe behavior for many repeated SurfaceInstance occurrences of the same Surface. SurfaceInstanceResolver does not reference concrete SurfaceInstance nodes and MUST NOT require one binding per repeated occurrence.

Input-modality profile references belong to the referenced ObservationEvent, not to ObservationBinding. A binding that references an event with requiredInputModalityProfileRefs uses those event-level profile references without changing its own surface, locator, or instance resolver contract.

Observability does not define graphNodeRef, surfaceRef, surfaceInstanceRef, or touchpoint boundary assignment such as compositeStateRefs. Those are Surface and Runtime terms. Observability does not define Runtime properties.

13. Locator Model

AccessibleLocator is the preferred interoperable locator for human-facing UI. It is based on the accessibility object exposed through an accessibility API, not on DOM structure, CSS selectors, Playwright expressions, or raw text content. WAI-ARIA defines an accessibility API as platform interfaces that expose object and event information to assistive technologies [WAI-ARIA-1.2].

AccessibleLocator.accessibleNameRef and AccessibleLocator.accessibleDescriptionRef reference localized MessageMeta nodes for the computed accessible-object name and description. For web DOM environments, producers and consumers SHOULD compute accessible-object names and descriptions according to [ACCNAME-1.2], then match the computed value against a locale-appropriate Message for the referenced message meta.

Observability does not define standard raw string fallback properties for accessible names or descriptions. Private adapter hints MAY appear in Core extensions, but such hints are not normative Observability terms.

An AccessibleLocator MUST provide at least one of:

  • role

  • accessibleNameRef

  • accessibleDescriptionRef

  • accessibleFeatureRefs

  • accessibleRelationRefs

  • contextLocatorRefs

AccessibleFeature names SHOULD be accessibility-model oriented, such as selected, expanded, disabled, checked, pressed, current, invalid, required, busy, or hidden. Producers SHOULD NOT use raw web-only names such as aria-selected when a platform-neutral state/property name is available.

AccessibleRelation names SHOULD also be accessibility-model oriented, such as controls, labelled-by, described-by, owns, active-descendant, details, or error-message.

contextLocatorRefs scope a locator by another accessible object. Multiple context locators are conjunctive.

CustomLocator is the escape hatch for stable semantic markers, CSS selectors, tool-specific queries, native automation identifiers, CLI patterns, server-log queries, kiosk signals, or other adapter-specific matching. A CustomLocator MUST define its semantics in Core extensions and is opaque to consumers that do not understand that extension.

14. Runtime Correlation

Runtime correlation is derived, not modeled as an Observability-to-Runtime reference.

text
RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceRef = ObservationBinding.observeSurfaceRef
RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceRef = ObservationBinding.observeSurfaceRef

An observation adapter that emits Runtime data SHOULD:

  1. match the binding's locatorRefs;

  2. when expectedMatchCount is present, compare the match count to that exact value;

  3. when surfaceInstanceResolverRef is present, read the resolver's instanceKeyFeatureRef from the matched accessible object or contextual accessible object;

  4. resolve or create the matching SurfaceInstance;

  5. emit the required Runtime surfaceInstanceRef.

For expectedMatchCount: 0, a satisfied absence contract does not provide a matched accessible object for instance resolution. Observability still does not require Runtime events to reference an ObservationBinding.

If an instance key is not exposed through the accessibility API, adapters MUST use CustomLocator or Core extensions for private resolver semantics. Runtime events MUST NOT be required to reference an ObservationBinding.

15. Normative Artifacts

This module is published through the following artifacts:

  • observability.ttl: ontology, published at https://ujg.specs.openuji.org/tr/1.0/ns/observability

  • observability.context.jsonld: JSON-LD term mappings, published at https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld

  • observability.shape.ttl: SHACL validation rules, published at https://ujg.specs.openuji.org/tr/1.0/ns/observability.shape

Examples in this page compose the shared baseline context https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld with the Surface, Localization, and Observability contexts. Runtime appears only in the informative correlation example.

15.1. Ontology

The normative Observability ontology is defined below and is published at https://ujg.specs.openuji.org/tr/1.0/ns/observability.

turtle
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/tr/1.0/ns/observability#> .
@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/> .

<https://ujg.specs.openuji.org/tr/1.0/ns/observability#> a owl:Ontology ;
  rdfs:label "UJG Observability 1.0 Vocabulary"@en ;
  dct:description "UJG Observability ontology declaration" .

### Classes

ujgobservability:ObservationBinding a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:ObservationEvent a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:InputModality a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:InputModalityProfile a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleLocator a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleFeature a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleRelation a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:CustomLocator a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:SurfaceInstanceResolver a owl:Class ;
  rdfs:subClassOf ujg:Node .

### Standard individuals

ujgobservability:keyboard a owl:NamedIndividual, ujgobservability:InputModality ;
  rdfs:label "Keyboard"@en ;
  rdfs:comment "The standard Observability input modality for keyboard-based interaction."@en .

ujgobservability:pointer a owl:NamedIndividual, ujgobservability:InputModality ;
  rdfs:label "Pointer"@en ;
  rdfs:comment "The standard Observability input modality for pointer-based interaction, including mouse, pen, touch, or equivalent pointing input."@en .

### Properties

ujgobservability:observeSurfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgsurface:Surface .

ujgobservability:observationEventRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgobservability:ObservationEvent .

ujgobservability:requiredInputModalityProfileRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationEvent ;
  rdfs:range ujgobservability:InputModalityProfile .

ujgobservability:inputModalityRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:InputModalityProfile ;
  rdfs:range ujgobservability:InputModality .

ujgobservability:locatorRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range [
    a owl:Class ;
    owl:unionOf (
      ujgobservability:AccessibleLocator
      ujgobservability:CustomLocator
    )
  ] .

ujgobservability:surfaceInstanceResolverRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgobservability:SurfaceInstanceResolver .

ujgobservability:expectedMatchCount a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range xsd:nonNegativeInteger .

ujgobservability:instanceKeyFeatureRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:SurfaceInstanceResolver ;
  rdfs:range ujgobservability:AccessibleFeature .

ujgobservability:role a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range xsd:string .

ujgobservability:accessibleNameRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgl10n:MessageMeta .

ujgobservability:accessibleDescriptionRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgl10n:MessageMeta .

ujgobservability:accessibleFeatureRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleFeature .

ujgobservability:accessibleRelationRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleRelation .

ujgobservability:contextLocatorRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleLocator .

ujgobservability:accessibleFeatureName a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleFeature ;
  rdfs:range xsd:string .

ujgobservability:accessibleFeatureValue a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleFeature ;
  rdfs:range xsd:string .

ujgobservability:accessibleRelationType a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleRelation ;
  rdfs:range xsd:string .

ujgobservability:targetLocatorRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleRelation ;
  rdfs:range ujgobservability:AccessibleLocator .
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/tr/1.0/ns/observability#> .
@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/> .

<https://ujg.specs.openuji.org/tr/1.0/ns/observability#> a owl:Ontology ;
  rdfs:label "UJG Observability 1.0 Vocabulary"@en ;
  dct:description "UJG Observability ontology declaration" .

### Classes

ujgobservability:ObservationBinding a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:ObservationEvent a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:InputModality a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:InputModalityProfile a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleLocator a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleFeature a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:AccessibleRelation a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:CustomLocator a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgobservability:SurfaceInstanceResolver a owl:Class ;
  rdfs:subClassOf ujg:Node .

### Standard individuals

ujgobservability:keyboard a owl:NamedIndividual, ujgobservability:InputModality ;
  rdfs:label "Keyboard"@en ;
  rdfs:comment "The standard Observability input modality for keyboard-based interaction."@en .

ujgobservability:pointer a owl:NamedIndividual, ujgobservability:InputModality ;
  rdfs:label "Pointer"@en ;
  rdfs:comment "The standard Observability input modality for pointer-based interaction, including mouse, pen, touch, or equivalent pointing input."@en .

### Properties

ujgobservability:observeSurfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgsurface:Surface .

ujgobservability:observationEventRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgobservability:ObservationEvent .

ujgobservability:requiredInputModalityProfileRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationEvent ;
  rdfs:range ujgobservability:InputModalityProfile .

ujgobservability:inputModalityRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:InputModalityProfile ;
  rdfs:range ujgobservability:InputModality .

ujgobservability:locatorRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range [
    a owl:Class ;
    owl:unionOf (
      ujgobservability:AccessibleLocator
      ujgobservability:CustomLocator
    )
  ] .

ujgobservability:surfaceInstanceResolverRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range ujgobservability:SurfaceInstanceResolver .

ujgobservability:expectedMatchCount a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:ObservationBinding ;
  rdfs:range xsd:nonNegativeInteger .

ujgobservability:instanceKeyFeatureRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:SurfaceInstanceResolver ;
  rdfs:range ujgobservability:AccessibleFeature .

ujgobservability:role a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range xsd:string .

ujgobservability:accessibleNameRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgl10n:MessageMeta .

ujgobservability:accessibleDescriptionRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgl10n:MessageMeta .

ujgobservability:accessibleFeatureRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleFeature .

ujgobservability:accessibleRelationRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleRelation .

ujgobservability:contextLocatorRefs a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleLocator ;
  rdfs:range ujgobservability:AccessibleLocator .

ujgobservability:accessibleFeatureName a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleFeature ;
  rdfs:range xsd:string .

ujgobservability:accessibleFeatureValue a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleFeature ;
  rdfs:range xsd:string .

ujgobservability:accessibleRelationType a owl:DatatypeProperty ;
  rdfs:domain ujgobservability:AccessibleRelation ;
  rdfs:range xsd:string .

ujgobservability:targetLocatorRef a owl:ObjectProperty ;
  rdfs:domain ujgobservability:AccessibleRelation ;
  rdfs:range ujgobservability:AccessibleLocator .

15.2. JSON-LD Context

The normative Observability JSON-LD context is defined below and is published at https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld.

json-ld
{
  "@context": {
    "@version": 1.1,

    "ujgobservability": "https://ujg.specs.openuji.org/tr/1.0/ns/observability#",
    "observability": "https://ujg.specs.openuji.org/tr/1.0/ns/observability#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",

    "ObservationBinding": "ujgobservability:ObservationBinding",
    "ObservationEvent": "ujgobservability:ObservationEvent",
    "InputModality": "ujgobservability:InputModality",
    "InputModalityProfile": "ujgobservability:InputModalityProfile",
    "AccessibleLocator": "ujgobservability:AccessibleLocator",
    "AccessibleFeature": "ujgobservability:AccessibleFeature",
    "AccessibleRelation": "ujgobservability:AccessibleRelation",
    "CustomLocator": "ujgobservability:CustomLocator",
    "SurfaceInstanceResolver": "ujgobservability:SurfaceInstanceResolver",

    "keyboard": "ujgobservability:keyboard",
    "pointer": "ujgobservability:pointer",

    "observeSurfaceRef": {
      "@id": "ujgobservability:observeSurfaceRef",
      "@type": "@id"
    },
    "observationEventRef": {
      "@id": "ujgobservability:observationEventRef",
      "@type": "@id"
    },
    "requiredInputModalityProfileRefs": {
      "@id": "ujgobservability:requiredInputModalityProfileRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "inputModalityRefs": {
      "@id": "ujgobservability:inputModalityRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "locatorRefs": {
      "@id": "ujgobservability:locatorRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "surfaceInstanceResolverRef": {
      "@id": "ujgobservability:surfaceInstanceResolverRef",
      "@type": "@id"
    },
    "expectedMatchCount": {
      "@id": "ujgobservability:expectedMatchCount",
      "@type": "xsd:nonNegativeInteger"
    },
    "instanceKeyFeatureRef": {
      "@id": "ujgobservability:instanceKeyFeatureRef",
      "@type": "@id"
    },
    "role": "ujgobservability:role",
    "accessibleNameRef": {
      "@id": "ujgobservability:accessibleNameRef",
      "@type": "@id"
    },
    "accessibleDescriptionRef": {
      "@id": "ujgobservability:accessibleDescriptionRef",
      "@type": "@id"
    },
    "accessibleFeatureRefs": {
      "@id": "ujgobservability:accessibleFeatureRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "accessibleRelationRefs": {
      "@id": "ujgobservability:accessibleRelationRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "contextLocatorRefs": {
      "@id": "ujgobservability:contextLocatorRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "accessibleFeatureName": "ujgobservability:accessibleFeatureName",
    "accessibleFeatureValue": "ujgobservability:accessibleFeatureValue",
    "accessibleRelationType": "ujgobservability:accessibleRelationType",
    "targetLocatorRef": {
      "@id": "ujgobservability:targetLocatorRef",
      "@type": "@id"
    }
  }
}
{
  "@context": {
    "@version": 1.1,

    "ujgobservability": "https://ujg.specs.openuji.org/tr/1.0/ns/observability#",
    "observability": "https://ujg.specs.openuji.org/tr/1.0/ns/observability#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",

    "ObservationBinding": "ujgobservability:ObservationBinding",
    "ObservationEvent": "ujgobservability:ObservationEvent",
    "InputModality": "ujgobservability:InputModality",
    "InputModalityProfile": "ujgobservability:InputModalityProfile",
    "AccessibleLocator": "ujgobservability:AccessibleLocator",
    "AccessibleFeature": "ujgobservability:AccessibleFeature",
    "AccessibleRelation": "ujgobservability:AccessibleRelation",
    "CustomLocator": "ujgobservability:CustomLocator",
    "SurfaceInstanceResolver": "ujgobservability:SurfaceInstanceResolver",

    "keyboard": "ujgobservability:keyboard",
    "pointer": "ujgobservability:pointer",

    "observeSurfaceRef": {
      "@id": "ujgobservability:observeSurfaceRef",
      "@type": "@id"
    },
    "observationEventRef": {
      "@id": "ujgobservability:observationEventRef",
      "@type": "@id"
    },
    "requiredInputModalityProfileRefs": {
      "@id": "ujgobservability:requiredInputModalityProfileRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "inputModalityRefs": {
      "@id": "ujgobservability:inputModalityRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "locatorRefs": {
      "@id": "ujgobservability:locatorRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "surfaceInstanceResolverRef": {
      "@id": "ujgobservability:surfaceInstanceResolverRef",
      "@type": "@id"
    },
    "expectedMatchCount": {
      "@id": "ujgobservability:expectedMatchCount",
      "@type": "xsd:nonNegativeInteger"
    },
    "instanceKeyFeatureRef": {
      "@id": "ujgobservability:instanceKeyFeatureRef",
      "@type": "@id"
    },
    "role": "ujgobservability:role",
    "accessibleNameRef": {
      "@id": "ujgobservability:accessibleNameRef",
      "@type": "@id"
    },
    "accessibleDescriptionRef": {
      "@id": "ujgobservability:accessibleDescriptionRef",
      "@type": "@id"
    },
    "accessibleFeatureRefs": {
      "@id": "ujgobservability:accessibleFeatureRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "accessibleRelationRefs": {
      "@id": "ujgobservability:accessibleRelationRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "contextLocatorRefs": {
      "@id": "ujgobservability:contextLocatorRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "accessibleFeatureName": "ujgobservability:accessibleFeatureName",
    "accessibleFeatureValue": "ujgobservability:accessibleFeatureValue",
    "accessibleRelationType": "ujgobservability:accessibleRelationType",
    "targetLocatorRef": {
      "@id": "ujgobservability:targetLocatorRef",
      "@type": "@id"
    }
  }
}

15.3. Validation

The normative Observability SHACL shape is defined below and is published at https://ujg.specs.openuji.org/tr/1.0/ns/observability.shape.

turtle
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/tr/1.0/ns/observability#> .
@prefix ujgobservabilityshape: <https://ujg.specs.openuji.org/tr/1.0/ns/observability.shape#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgobservabilityshape:LocatorShape a sh:NodeShape ;
  sh:nodeKind sh:IRI ;
  sh:or (
    [ sh:class ujgobservability:AccessibleLocator ]
    [ sh:class ujgobservability:CustomLocator ]
  ) .

ujgobservabilityshape:ObservationBindingShape a sh:NodeShape ;
  sh:targetClass ujgobservability:ObservationBinding ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:observeSurfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:observationEventRef ;
    sh:class ujgobservability:ObservationEvent ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:locatorRefs ;
    sh:node ujgobservabilityshape:LocatorShape ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:surfaceInstanceResolverRef ;
    sh:class ujgobservability:SurfaceInstanceResolver ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:expectedMatchCount ;
    sh:datatype xsd:nonNegativeInteger ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:ObservationEventShape a sh:NodeShape ;
  sh:targetClass ujgobservability:ObservationEvent ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:requiredInputModalityProfileRefs ;
    sh:class ujgobservability:InputModalityProfile ;
    sh:nodeKind sh:IRI ;
  ] .

ujgobservabilityshape:InputModalityShape a sh:NodeShape ;
  sh:targetClass ujgobservability:InputModality ;
  sh:nodeKind sh:IRI .

ujgobservabilityshape:InputModalityProfileShape a sh:NodeShape ;
  sh:targetClass ujgobservability:InputModalityProfile ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:inputModalityRefs ;
    sh:class ujgobservability:InputModality ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] .

ujgobservabilityshape:SurfaceInstanceResolverShape a sh:NodeShape ;
  sh:targetClass ujgobservability:SurfaceInstanceResolver ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:instanceKeyFeatureRef ;
    sh:class ujgobservability:AccessibleFeature ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:AccessibleLocatorShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleLocator ;
  sh:nodeKind sh:IRI ;

  sh:or (
    [ sh:property [ sh:path ujgobservability:role ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleNameRef ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleDescriptionRef ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleFeatureRefs ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleRelationRefs ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:contextLocatorRefs ; sh:minCount 1 ] ]
  ) ;

  sh:property [
    sh:path ujgobservability:role ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleNameRef ;
    sh:class ujgl10n:MessageMeta ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleDescriptionRef ;
    sh:class ujgl10n:MessageMeta ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureRefs ;
    sh:class ujgobservability:AccessibleFeature ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleRelationRefs ;
    sh:class ujgobservability:AccessibleRelation ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:property [
    sh:path ujgobservability:contextLocatorRefs ;
    sh:class ujgobservability:AccessibleLocator ;
    sh:nodeKind sh:IRI ;
  ] .

ujgobservabilityshape:AccessibleFeatureShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleFeature ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureName ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureValue ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:AccessibleRelationShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleRelation ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:accessibleRelationType ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:targetLocatorRef ;
    sh:class ujgobservability:AccessibleLocator ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:CustomLocatorShape a sh:NodeShape ;
  sh:targetClass ujgobservability:CustomLocator ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujg:extensions ;
    sh:datatype rdf:JSON ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/tr/1.0/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/tr/1.0/ns/observability#> .
@prefix ujgobservabilityshape: <https://ujg.specs.openuji.org/tr/1.0/ns/observability.shape#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgobservabilityshape:LocatorShape a sh:NodeShape ;
  sh:nodeKind sh:IRI ;
  sh:or (
    [ sh:class ujgobservability:AccessibleLocator ]
    [ sh:class ujgobservability:CustomLocator ]
  ) .

ujgobservabilityshape:ObservationBindingShape a sh:NodeShape ;
  sh:targetClass ujgobservability:ObservationBinding ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:observeSurfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:observationEventRef ;
    sh:class ujgobservability:ObservationEvent ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:locatorRefs ;
    sh:node ujgobservabilityshape:LocatorShape ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:surfaceInstanceResolverRef ;
    sh:class ujgobservability:SurfaceInstanceResolver ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:expectedMatchCount ;
    sh:datatype xsd:nonNegativeInteger ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:ObservationEventShape a sh:NodeShape ;
  sh:targetClass ujgobservability:ObservationEvent ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:requiredInputModalityProfileRefs ;
    sh:class ujgobservability:InputModalityProfile ;
    sh:nodeKind sh:IRI ;
  ] .

ujgobservabilityshape:InputModalityShape a sh:NodeShape ;
  sh:targetClass ujgobservability:InputModality ;
  sh:nodeKind sh:IRI .

ujgobservabilityshape:InputModalityProfileShape a sh:NodeShape ;
  sh:targetClass ujgobservability:InputModalityProfile ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:inputModalityRefs ;
    sh:class ujgobservability:InputModality ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] .

ujgobservabilityshape:SurfaceInstanceResolverShape a sh:NodeShape ;
  sh:targetClass ujgobservability:SurfaceInstanceResolver ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:instanceKeyFeatureRef ;
    sh:class ujgobservability:AccessibleFeature ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:AccessibleLocatorShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleLocator ;
  sh:nodeKind sh:IRI ;

  sh:or (
    [ sh:property [ sh:path ujgobservability:role ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleNameRef ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleDescriptionRef ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleFeatureRefs ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:accessibleRelationRefs ; sh:minCount 1 ] ]
    [ sh:property [ sh:path ujgobservability:contextLocatorRefs ; sh:minCount 1 ] ]
  ) ;

  sh:property [
    sh:path ujgobservability:role ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleNameRef ;
    sh:class ujgl10n:MessageMeta ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleDescriptionRef ;
    sh:class ujgl10n:MessageMeta ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureRefs ;
    sh:class ujgobservability:AccessibleFeature ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleRelationRefs ;
    sh:class ujgobservability:AccessibleRelation ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:property [
    sh:path ujgobservability:contextLocatorRefs ;
    sh:class ujgobservability:AccessibleLocator ;
    sh:nodeKind sh:IRI ;
  ] .

ujgobservabilityshape:AccessibleFeatureShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleFeature ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureName ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:accessibleFeatureValue ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:AccessibleRelationShape a sh:NodeShape ;
  sh:targetClass ujgobservability:AccessibleRelation ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgobservability:accessibleRelationType ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgobservability:targetLocatorRef ;
    sh:class ujgobservability:AccessibleLocator ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgobservabilityshape:CustomLocatorShape a sh:NodeShape ;
  sh:targetClass ujgobservability:CustomLocator ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujg:extensions ;
    sh:datatype rdf:JSON ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

The rules below define the remaining module semantics beyond the structural constraints captured by the SHACL shape.

  1. Surface first: An ObservationBinding MUST identify exactly one Surface using observeSurfaceRef.

  2. No graph traversal: Observability properties MUST NOT change Graph validity, graph traversal behavior, import resolution, or core node identity.

  3. No Runtime dependency: Observability MUST NOT require Runtime data and MUST NOT define a Runtime property.

  4. Derived Runtime correlation: Consumers MAY correlate Runtime events to bindings by matching RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceRef to ObservationBinding.observeSurfaceRef.

  5. Conjunctive locators: locatorRefs inside one ObservationBinding are conjunctive.

  6. Exact match counts: When expectedMatchCount is present on an ObservationBinding, consumers that evaluate the binding MUST compare the number of objects matching the full conjunctive locator contract in the current recognition scope to that exact non-negative integer. expectedMatchCount: 0 means the locator contract is expected to find no matching objects. When expectedMatchCount is omitted, consumers MUST NOT infer exact cardinality from the binding.

  7. Event-level modality profiles: Input-modality profile references MUST be declared on ObservationEvent with requiredInputModalityProfileRefs, not on ObservationBinding or Graph Transition nodes.

  8. Profile modality references: InputModalityProfile.inputModalityRefs values identify InputModality nodes. Consumers MUST NOT infer interaction order from the order of values.

  9. Standard and owner-defined modality IRIs: Event identifiers remain producer-defined. Observability reserves observability:keyboard and observability:pointer as standard InputModality identifiers; producers define other concrete modality identifiers.

  10. Instance resolver: SurfaceInstanceResolver.instanceKeyFeatureRef MUST identify one AccessibleFeature that supplies the instance key source. A resolver MUST NOT reference concrete SurfaceInstance nodes.

  11. Accessible-object semantics: AccessibleLocator identifies an accessible object, not an implementation node or selector expression.

  12. Localized name and description matching: accessibleNameRef and accessibleDescriptionRef MUST resolve to MessageMeta nodes. In web DOM environments, adapters SHOULD compute accessible names and descriptions according to [ACCNAME-1.2], then match the computed values against locale-appropriate Message values for those message metas.

  13. Accessibility API orientation: Role, feature, and relation names SHOULD describe accessibility API concepts rather than DOM or tool-specific implementation details [WAI-ARIA-1.2].

  14. Opaque custom locators: CustomLocator semantics live in Core extensions; consumers that do not understand the extension MAY ignore the locator semantics.

  15. Graceful degradation: Consumers that do not implement Observability semantics MAY ignore Observability data, but SHOULD preserve recognized JSON-LD data during read-transform-write when possible.

16. Examples

16.1. Minimal Example

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/share.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:bob-pending-federated-share",
      "label": "Bob pending federated share"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:bob-pending-share",
      "graphNodeRef": "urn:state:bob-pending-federated-share"
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:presence",
      "label": "Presence"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:selected-true",
      "label": "Selected true",
      "accessibleFeatureName": "selected",
      "accessibleFeatureValue": "true"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:file-id",
      "label": "File identifier",
      "accessibleFeatureName": "file-id",
      "accessibleFeatureValue": "*"
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:files",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:files:en",
      "messageMetaRef": "urn:message-meta:files",
      "localeRef": "urn:locale:en",
      "value": "Files"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:shared-with-you",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:shared-with-you:en",
      "messageMetaRef": "urn:message-meta:shared-with-you",
      "localeRef": "urn:locale:en",
      "value": "Shared with you"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:files-heading",
      "label": "Files heading",
      "role": "heading",
      "accessibleNameRef": "urn:message-meta:files"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:shared-with-you-tab-selected",
      "label": "Selected Shared with you tab",
      "role": "tab",
      "accessibleNameRef": "urn:message-meta:shared-with-you",
      "accessibleFeatureRefs": [
        "urn:feature:selected-true"
      ]
    },
    {
      "@type": "SurfaceInstanceResolver",
      "@id": "urn:resolver:bob-pending-share-file-id",
      "label": "Pending share file identifier resolver",
      "instanceKeyFeatureRef": "urn:feature:file-id"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:bob-pending-share-present",
      "label": "Bob sees pending federated share",
      "observeSurfaceRef": "urn:surface:bob-pending-share",
      "observationEventRef": "urn:observation-event:presence",
      "surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
      "locatorRefs": [
        "urn:locator:files-heading",
        "urn:locator:shared-with-you-tab-selected"
      ]
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/share.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:bob-pending-federated-share",
      "label": "Bob pending federated share"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:bob-pending-share",
      "graphNodeRef": "urn:state:bob-pending-federated-share"
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:presence",
      "label": "Presence"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:selected-true",
      "label": "Selected true",
      "accessibleFeatureName": "selected",
      "accessibleFeatureValue": "true"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:file-id",
      "label": "File identifier",
      "accessibleFeatureName": "file-id",
      "accessibleFeatureValue": "*"
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:files",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:files:en",
      "messageMetaRef": "urn:message-meta:files",
      "localeRef": "urn:locale:en",
      "value": "Files"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:shared-with-you",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:shared-with-you:en",
      "messageMetaRef": "urn:message-meta:shared-with-you",
      "localeRef": "urn:locale:en",
      "value": "Shared with you"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:files-heading",
      "label": "Files heading",
      "role": "heading",
      "accessibleNameRef": "urn:message-meta:files"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:shared-with-you-tab-selected",
      "label": "Selected Shared with you tab",
      "role": "tab",
      "accessibleNameRef": "urn:message-meta:shared-with-you",
      "accessibleFeatureRefs": [
        "urn:feature:selected-true"
      ]
    },
    {
      "@type": "SurfaceInstanceResolver",
      "@id": "urn:resolver:bob-pending-share-file-id",
      "label": "Pending share file identifier resolver",
      "instanceKeyFeatureRef": "urn:feature:file-id"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:bob-pending-share-present",
      "label": "Bob sees pending federated share",
      "observeSurfaceRef": "urn:surface:bob-pending-share",
      "observationEventRef": "urn:observation-event:presence",
      "surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
      "locatorRefs": [
        "urn:locator:files-heading",
        "urn:locator:shared-with-you-tab-selected"
      ]
    }
  ]
}

16.2. Input Modality Requirement Example

This example shows a producer-defined activation event for a transition affordance surface. The event references two producer-defined modality profiles that use standard keyboard and pointer modality identifiers.

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/activation-modalities.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:checkout-ready",
      "label": "Checkout ready"
    },
    {
      "@type": "State",
      "@id": "urn:state:checkout-submitted",
      "label": "Checkout submitted"
    },
    {
      "@type": "Transition",
      "@id": "urn:transition:submit-checkout",
      "label": "Submit checkout",
      "from": "urn:state:checkout-ready",
      "to": "urn:state:checkout-submitted"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:submit-checkout",
      "graphNodeRef": "urn:transition:submit-checkout"
    },
    {
      "@type": "InputModalityProfile",
      "@id": "urn:input-modality-profile:keyboard",
      "label": "Keyboard",
      "inputModalityRefs": [
        "observability:keyboard"
      ]
    },
    {
      "@type": "InputModalityProfile",
      "@id": "urn:input-modality-profile:pointer",
      "label": "Pointer",
      "inputModalityRefs": [
        "observability:pointer"
      ]
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:submit-checkout-activation",
      "label": "Submit checkout activation",
      "requiredInputModalityProfileRefs": [
        "urn:input-modality-profile:keyboard",
        "urn:input-modality-profile:pointer"
      ]
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:submit-checkout",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:submit-checkout:en",
      "messageMetaRef": "urn:message-meta:submit-checkout",
      "localeRef": "urn:locale:en",
      "value": "Submit checkout"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:submit-checkout",
      "role": "button",
      "accessibleNameRef": "urn:message-meta:submit-checkout"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:submit-checkout-activation",
      "observeSurfaceRef": "urn:surface:submit-checkout",
      "observationEventRef": "urn:observation-event:submit-checkout-activation",
      "locatorRefs": [
        "urn:locator:submit-checkout"
      ]
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/activation-modalities.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:checkout-ready",
      "label": "Checkout ready"
    },
    {
      "@type": "State",
      "@id": "urn:state:checkout-submitted",
      "label": "Checkout submitted"
    },
    {
      "@type": "Transition",
      "@id": "urn:transition:submit-checkout",
      "label": "Submit checkout",
      "from": "urn:state:checkout-ready",
      "to": "urn:state:checkout-submitted"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:submit-checkout",
      "graphNodeRef": "urn:transition:submit-checkout"
    },
    {
      "@type": "InputModalityProfile",
      "@id": "urn:input-modality-profile:keyboard",
      "label": "Keyboard",
      "inputModalityRefs": [
        "observability:keyboard"
      ]
    },
    {
      "@type": "InputModalityProfile",
      "@id": "urn:input-modality-profile:pointer",
      "label": "Pointer",
      "inputModalityRefs": [
        "observability:pointer"
      ]
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:submit-checkout-activation",
      "label": "Submit checkout activation",
      "requiredInputModalityProfileRefs": [
        "urn:input-modality-profile:keyboard",
        "urn:input-modality-profile:pointer"
      ]
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:submit-checkout",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:submit-checkout:en",
      "messageMetaRef": "urn:message-meta:submit-checkout",
      "localeRef": "urn:locale:en",
      "value": "Submit checkout"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:submit-checkout",
      "role": "button",
      "accessibleNameRef": "urn:message-meta:submit-checkout"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:submit-checkout-activation",
      "observeSurfaceRef": "urn:surface:submit-checkout",
      "observationEventRef": "urn:observation-event:submit-checkout-activation",
      "locatorRefs": [
        "urn:locator:submit-checkout"
      ]
    }
  ]
}

16.3. Runtime Correlation Example

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/runtime.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/runtime-correlation.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:bob-pending-federated-share",
      "label": "Bob pending federated share"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:bob-pending-share",
      "graphNodeRef": "urn:state:bob-pending-federated-share"
    },
    {
      "@type": "SurfaceInstance",
      "@id": "urn:surface-instance:bob-pending-share:shared-folder-42",
      "surfaceRef": "urn:surface:bob-pending-share"
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:presence",
      "label": "Presence"
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:files",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:files:en",
      "messageMetaRef": "urn:message-meta:files",
      "localeRef": "urn:locale:en",
      "value": "Files"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:shared-folder-42",
      "accessibleFeatureName": "file-id",
      "accessibleFeatureValue": "shared-folder-42"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:files-heading",
      "role": "heading",
      "accessibleNameRef": "urn:message-meta:files"
    },
    {
      "@type": "SurfaceInstanceResolver",
      "@id": "urn:resolver:bob-pending-share-file-id",
      "instanceKeyFeatureRef": "urn:feature:shared-folder-42"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:bob-pending-share-present",
      "observeSurfaceRef": "urn:surface:bob-pending-share",
      "observationEventRef": "urn:observation-event:presence",
      "surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
      "locatorRefs": [
        "urn:locator:files-heading"
      ]
    },
    {
      "@type": "JourneyExecution",
      "@id": "urn:execution:fed-share-runtime-001"
    },
    {
      "@type": "RuntimeEvent",
      "@id": "urn:runtime-event:bob-pending-share-present-001",
      "executionId": "urn:execution:fed-share-runtime-001",
      "surfaceInstanceRef": "urn:surface-instance:bob-pending-share:shared-folder-42"
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/l10n.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/runtime.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/observability.context.jsonld"
  ],
  "@id": "https://example.com/ujg/observability/runtime-correlation.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "State",
      "@id": "urn:state:bob-pending-federated-share",
      "label": "Bob pending federated share"
    },
    {
      "@type": "Surface",
      "@id": "urn:surface:bob-pending-share",
      "graphNodeRef": "urn:state:bob-pending-federated-share"
    },
    {
      "@type": "SurfaceInstance",
      "@id": "urn:surface-instance:bob-pending-share:shared-folder-42",
      "surfaceRef": "urn:surface:bob-pending-share"
    },
    {
      "@type": "ObservationEvent",
      "@id": "urn:observation-event:presence",
      "label": "Presence"
    },
    {
      "@type": "Locale",
      "@id": "urn:locale:en",
      "localeCode": "en"
    },
    {
      "@type": "MessageMeta",
      "@id": "urn:message-meta:files",
      "defaultLocaleRef": "urn:locale:en"
    },
    {
      "@type": "Message",
      "@id": "urn:message:files:en",
      "messageMetaRef": "urn:message-meta:files",
      "localeRef": "urn:locale:en",
      "value": "Files"
    },
    {
      "@type": "AccessibleFeature",
      "@id": "urn:feature:shared-folder-42",
      "accessibleFeatureName": "file-id",
      "accessibleFeatureValue": "shared-folder-42"
    },
    {
      "@type": "AccessibleLocator",
      "@id": "urn:locator:files-heading",
      "role": "heading",
      "accessibleNameRef": "urn:message-meta:files"
    },
    {
      "@type": "SurfaceInstanceResolver",
      "@id": "urn:resolver:bob-pending-share-file-id",
      "instanceKeyFeatureRef": "urn:feature:shared-folder-42"
    },
    {
      "@type": "ObservationBinding",
      "@id": "urn:binding:bob-pending-share-present",
      "observeSurfaceRef": "urn:surface:bob-pending-share",
      "observationEventRef": "urn:observation-event:presence",
      "surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
      "locatorRefs": [
        "urn:locator:files-heading"
      ]
    },
    {
      "@type": "JourneyExecution",
      "@id": "urn:execution:fed-share-runtime-001"
    },
    {
      "@type": "RuntimeEvent",
      "@id": "urn:runtime-event:bob-pending-share-present-001",
      "executionId": "urn:execution:fed-share-runtime-001",
      "surfaceInstanceRef": "urn:surface-instance:bob-pending-share:shared-folder-42"
    }
  ]
}

The runtime event can be correlated to urn:binding:bob-pending-share-present because its referenced surface instance points back to urn:surface:bob-pending-share. The event does not reference the binding.

Copyright © 2026 the Contributors to the ujg/modules/observability/1.0-rc1, published by the User Journal Graph Community Group under the W3C Community Contributor License Agreement (CLA) . A human-readable summary is available.

generated by Speculator