@phase2 @uko @ontology
Feature: UKO Ontology Loader
  As a CleverAgents developer
  I want to parse and validate the UKO ontology from TTL files
  So that the system can reason about code artifacts and their relationships

  # ---------------------------------------------------------------------------
  # Prefix parsing
  # ---------------------------------------------------------------------------

  @uko_prefix
  Scenario: Parse prefix line correctly
    Given a TTL string:
      """
      @prefix uko: <https://cleveragents.ai/ontology/uko#> .
      @prefix uko-code: <https://cleveragents.ai/ontology/uko/code#> .
      @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

      uko: a owl:Ontology ;
          owl:versionIRI <https://cleveragents.ai/ontology/uko/0.1.0> ;
          rdfs:label "Test" ;
          rdfs:comment "Test ontology" .
      """
    When I parse the TTL string
    Then the prefix "uko" should map to "https://cleveragents.ai/ontology/uko#"
    And the prefix "uko-code" should map to "https://cleveragents.ai/ontology/uko/code#"
    And the prefix "rdf" should map to "http://www.w3.org/1999/02/22-rdf-syntax-ns#"

  # ---------------------------------------------------------------------------
  # Layer 0 — Universal Foundation
  # ---------------------------------------------------------------------------

  @uko_layer0
  Scenario: Parse Layer 0 nodes from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then I should find a node with label "InformationUnit"
    And I should find a node with label "Container"
    And I should find a node with label "Atom"
    And I should find a node with label "Annotation"
    And I should find a node with label "Boundary"

  # ---------------------------------------------------------------------------
  # Layer 1 — General Software
  # ---------------------------------------------------------------------------

  @uko_layer1
  Scenario: Parse Layer 1 nodes from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 1
    Then I should find a node with label "Module"
    And I should find a node with label "Callable"
    And I should find a node with label "TypeDefinition"
    And I should find a node with label "TestCase"
    And I should find a node with label "Import"

  # ---------------------------------------------------------------------------
  # Layer 2 — Object-Oriented Paradigm
  # ---------------------------------------------------------------------------

  @uko_layer2
  Scenario: Parse Layer 2 nodes from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 2
    Then I should find a node with label "Class"
    And I should find a node with label "Interface"
    And I should find a node with label "Method"
    And I should find a node with label "Attribute"

  # ---------------------------------------------------------------------------
  # Layer 0 properties (relationships)
  # ---------------------------------------------------------------------------

  @uko_layer0_props
  Scenario: Parse Layer 0 relationship properties from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then I should find a node with label "contains"
    And I should find a node with label "references"
    And I should find a node with label "dependsOn"

  # ---------------------------------------------------------------------------
  # Version metadata
  # ---------------------------------------------------------------------------

  @uko_version
  Scenario: Version metadata extracted correctly
    Given the UKO ontology is loaded from the TTL file
    Then the ontology version should be "0.1.0"
    And the ontology label should be "Unified Knowledge Ontology"
    And the ontology comment should be "CleverAgents knowledge representation layers 0-3"
    And the version IRI should be "https://cleveragents.ai/ontology/uko/0.1.0"

  # ---------------------------------------------------------------------------
  # Validation errors
  # ---------------------------------------------------------------------------

  @uko_validation @error_handling
  Scenario: Parser skips nodes without rdf_type
    Given a TTL string with a node missing rdf_type:
      """
      @prefix uko: <https://cleveragents.ai/ontology/uko#> .

      uko: a owl:Ontology ;
          owl:versionIRI <https://cleveragents.ai/ontology/uko/0.1.0> ;
          rdfs:label "Test" ;
          rdfs:comment "Test" .

      uko:Broken rdfs:label "Broken" .
      """
    When I parse the TTL string expecting no nodes
    Then no nodes should be present in the ontology

  @uko_validation @error_handling
  Scenario: Validate rejects ontology with typeless node
    Given the UKO ontology is loaded from the TTL file
    When I inject a node without rdf_type into the ontology
    And I validate the modified ontology
    Then validation errors should include "missing rdf:type"

  @uko_validation @error_handling
  Scenario: Validate rejects undefined prefix
    Given a UKO ontology with an undefined prefix node
    When I validate the ontology
    Then the validation errors should mention "undefined prefix"

  @uko_validation
  Scenario: Validate accepts valid ontology
    Given the UKO ontology is loaded from the TTL file
    When I validate the ontology
    Then there should be no validation errors

  @uko_validation @error_handling
  Scenario: Validate rejects non-existent parent URI
    Given a UKO ontology with a node referencing a non-existent parent
    When I validate the ontology
    Then the validation errors should mention "non-existent parent"

  # ---------------------------------------------------------------------------
  # Inheritance resolution
  # ---------------------------------------------------------------------------

  @uko_inheritance
  Scenario: Resolve inheritance DAG for uko-oo:Class (multi-parent)
    Given the UKO ontology is loaded from the TTL file
    When I resolve inheritance for "https://cleveragents.ai/ontology/uko/oo#Class"
    Then the inheritance chain should have at least 5 nodes
    And the first node in the chain should have label "Class"
    And the last node in the chain should have label "InformationUnit"

  @uko_inheritance
  Scenario: Resolve inheritance chain for Container (Layer 0)
    Given the UKO ontology is loaded from the TTL file
    When I resolve inheritance for "https://cleveragents.ai/ontology/uko#Container"
    Then the inheritance chain should have at least 2 nodes
    And the first node in the chain should have label "Container"

  @uko_inheritance @multi_parent
  Scenario: uko-oo:Class has dual rdfs:subClassOf parents
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 2
    Then the node with label "Class" should have parent "https://cleveragents.ai/ontology/uko/code#TypeDefinition"
    And the node with label "Class" should have parent "https://cleveragents.ai/ontology/uko#Container"

  @uko_inheritance @multi_parent
  Scenario: uko-oo:Interface has dual rdfs:subClassOf parents
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 2
    Then the node with label "Interface" should have parent "https://cleveragents.ai/ontology/uko/code#TypeDefinition"
    And the node with label "Interface" should have parent "https://cleveragents.ai/ontology/uko#Boundary"

  # ---------------------------------------------------------------------------
  # Layer query
  # ---------------------------------------------------------------------------

  @uko_layer_query
  Scenario: Get all nodes at specific layer
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then there should be at least 18 nodes

  @uko_layer
  Scenario Outline: Get correct node count for layer <layer>
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer <layer>
    Then the node count should be <count>

    Examples:
      | layer | count |
      | 0     | 18    |
      | 1     | 67    |
      | 2     | 14    |

  # ---------------------------------------------------------------------------
  # rdfs:domain and rdfs:range URI resolution
  # ---------------------------------------------------------------------------

  @uko_domain_range
  Scenario: rdfs:domain values are resolved to full URIs
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then the node with label "contains" should have property "rdfs:domain" resolved to a full URI
    And the node with label "contains" should have property "rdfs:range" resolved to a full URI

  @uko_domain_range
  Scenario: rdfs:subPropertyOf values are resolved to full URIs
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 2
    Then the node with label "inheritsFrom" should have property "rdfs:subPropertyOf" resolved to a full URI

  # ---------------------------------------------------------------------------
  # Integration: load actual file
  # ---------------------------------------------------------------------------

  @uko_integration
  Scenario: Load the actual uko.ttl file successfully
    Given the UKO ontology is loaded from the TTL file
    Then the ontology should have prefixes defined
    And the ontology should have nodes defined

  # ---------------------------------------------------------------------------
  # Version registry
  # ---------------------------------------------------------------------------

  @uko_version
  Scenario: Version registry contains 0.1.0
    Given the UKO ontology is loaded from the TTL file
    Then "0.1.0" should be in the supported versions

  # ---------------------------------------------------------------------------
  # Layer 0 content, provenance, and temporal properties
  # ---------------------------------------------------------------------------

  @uko_layer0_props
  Scenario: Parse Layer 0 content properties from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then I should find a node with label "hasRendering"
    And I should find a node with label "renderingDepth"
    And I should find a node with label "hasFullContent"

  @uko_layer0_props
  Scenario: Parse Layer 0 provenance properties from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then I should find a node with label "sourceResource"
    And I should find a node with label "sourcePath"
    And I should find a node with label "sourceRange"

  @uko_layer0_props
  Scenario: Parse Layer 0 temporal properties from TTL
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then I should find a node with label "validFrom"
    And I should find a node with label "validUntil"
    And I should find a node with label "isCurrent"
    And I should find a node with label "isRevisionOf"

  # ---------------------------------------------------------------------------
  # rdfs:domain / rdfs:range correctness for content, provenance, temporal props
  # ---------------------------------------------------------------------------

  @uko_domain_range
  Scenario: Content properties have correct rdfs:domain and rdfs:range
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then the node with label "hasRendering" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "hasRendering" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#string"
    And the node with label "renderingDepth" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "renderingDepth" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#nonNegativeInteger"
    And the node with label "hasFullContent" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "hasFullContent" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#string"

  @uko_domain_range
  Scenario: Provenance properties have correct rdfs:domain and rdfs:range
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then the node with label "sourceResource" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "sourceResource" should not have property "rdfs:range"
    And the node with label "sourcePath" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "sourcePath" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#string"
    And the node with label "sourceRange" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "sourceRange" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#string"

  @uko_domain_range
  Scenario: Temporal properties have correct rdfs:domain and rdfs:range
    Given the UKO ontology is loaded from the TTL file
    When I get nodes at layer 0
    Then the node with label "validFrom" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "validFrom" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#dateTime"
    And the node with label "validUntil" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "validUntil" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#dateTime"
    And the node with label "isCurrent" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "isCurrent" should have property "rdfs:range" equal to "http://www.w3.org/2001/XMLSchema#boolean"
    And the node with label "isRevisionOf" should have property "rdfs:domain" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"
    And the node with label "isRevisionOf" should have property "rdfs:range" equal to "https://cleveragents.ai/ontology/uko#InformationUnit"

  # ---------------------------------------------------------------------------
  # Unsupported version rejection
  # ---------------------------------------------------------------------------

  @uko_validation @error_handling
  Scenario: Loader rejects unsupported ontology version
    Given a TTL string:
      """
      @prefix uko: <https://cleveragents.ai/ontology/uko#> .
      @prefix owl: <http://www.w3.org/2002/07/owl#> .
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

      uko: a owl:Ontology ;
          owl:versionIRI <https://cleveragents.ai/ontology/uko/99.0.0> ;
          rdfs:label "Test" ;
          rdfs:comment "Test" .
      """
    When I attempt to parse the TTL string expecting a validation error
    Then a validation error should mention "Unsupported version"

  @uko_validation @error_handling
  Scenario: Loader rejects version IRI with non-semver last segment
    Given a TTL string:
      """
      @prefix uko: <https://cleveragents.ai/ontology/uko#> .
      @prefix owl: <http://www.w3.org/2002/07/owl#> .
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

      uko: a owl:Ontology ;
          owl:versionIRI <https://cleveragents.ai/ontology/uko> ;
          rdfs:label "Test" ;
          rdfs:comment "Test" .
      """
    When I attempt to parse the TTL string expecting a validation error
    Then a validation error should mention "Unsupported version"

  # ---------------------------------------------------------------------------
  # Duplicate-key handling in properties tuple
  # ---------------------------------------------------------------------------

  @uko_properties
  Scenario: Duplicate keys in properties tuple preserve last value when cast to dict
    Given a UKO node with duplicate property keys
    When I convert the node properties to a dict
    Then the dict should contain only the last value for the duplicated key

  # ---------------------------------------------------------------------------
  # Cycle detection
  # ---------------------------------------------------------------------------

  @uko_inheritance @error_handling
  Scenario: Cycle detection in inheritance
    Given a UKO ontology with a cycle in inheritance
    When I attempt to resolve inheritance for the cyclic node
    Then a cycle detection error should be raised
