Files
hamza.khyari 3c014a9565
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 19s
CI / e2e_tests (pull_request) Successful in 23s
CI / typecheck (pull_request) Successful in 32s
CI / security (pull_request) Successful in 43s
CI / unit_tests (pull_request) Successful in 2m2s
CI / integration_tests (pull_request) Successful in 2m41s
CI / docker (pull_request) Successful in 49s
CI / coverage (pull_request) Successful in 5m32s
CI / benchmark-regression (pull_request) Successful in 36m2s
feat(acms): implement UKO Layer 2 Paradigm Vocabularies (uko-oo, uko-func, uko-proc)
2026-03-13 18:21:50 +00:00

353 lines
16 KiB
Gherkin

@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