04f24b39c0
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 / security (pull_request) Successful in 33s
CI / typecheck (pull_request) Successful in 38s
CI / unit_tests (pull_request) Successful in 2m26s
CI / docker (pull_request) Successful in 40s
CI / integration_tests (pull_request) Successful in 3m29s
CI / coverage (pull_request) Successful in 4m30s
CI / benchmark-regression (pull_request) Has been cancelled
Implement the four Layer 1 domain-specific OWL/Turtle ontology vocabularies that specialize Layer 0 universal concepts for specific knowledge domains. Ontology (docs/ontology/uko.ttl): - Added uko-doc: namespace with 17 classes (Document, Part, Chapter, Section, Subsection, Paragraph, Sentence, CodeBlock, Citation, Figure, Table, Footnote, Annotation, Bookmark, CrossReference, PageBreak, SectionBreak), 5 properties, and 4 relationships - Added uko-data: namespace with 13 classes (Schema, Table, Column, View, StoredProcedure, Constraint, Index, ForeignKey, Trigger, Annotation, Bookmark, PartitionBoundary, ShardBoundary), 6 properties, and 5 relationships - Added uko-infra: namespace with 7 classes (Service, Network, Endpoint, ConfigKey, Volume, FirewallRule, SubnetBoundary) and 2 relationships - All classes use rdfs:subClassOf from Layer 0 base classes Domain registry (ontology_registry.py): - DomainDescriptor dataclass with namespace IRI, prefix, layer, classes, superclass mappings, and DetailLevelMap - Registry functions: get_domain(), list_domains(), get_layer1_domains() - DetailLevelMap chain builder for hierarchical depth resolution - Turtle validation with TurtleValidationError (no rdflib dependency) - All DetailLevelMap data inlined to maintain DIP compliance (domain layer does not import from application layer) DetailLevelMap presets (depth_breadth_projection.py): - code_detail_map: 10 spec-complete levels (depths 0-9) - docs_detail_map: 11 spec-complete levels (depths 0-10) - database_detail_map: 12 spec-complete levels (depths 0-11) - infra_detail_map: 9 spec-complete levels (depths 0-8) Tests: - 31 BDD scenarios in uko_ontology_registry.feature covering domain lookup, all DetailLevelMap levels, inheritance chains, Turtle validation, Universal View Guarantee, and negative/edge cases - 6 Robot Framework integration tests - Updated existing tests: depth_breadth_projection.feature (TABLE_LISTING depth 0->1, added SCHEMA_LISTING), uko_ontology.feature (Layer 1 node count 8->67) Spec reference: docs/specification.md §41830-42332 ISSUES CLOSED: #574
168 lines
5.4 KiB
Python
168 lines
5.4 KiB
Python
"""Robot Framework helper for UKO Ontology Registry integration smoke tests.
|
|
|
|
Exercises domain lookup, DetailLevelMap resolution across all four
|
|
Layer 1 domains, inheritance chain building, and Turtle validation
|
|
against the project ontology file.
|
|
|
|
Usage::
|
|
|
|
python robot/helper_uko_ontology_registry.py <command>
|
|
|
|
Commands
|
|
--------
|
|
domain_lookup
|
|
Look up each domain prefix and verify IRI / layer / class count.
|
|
detail_level_resolution
|
|
Resolve named levels for every Layer 1 domain.
|
|
inheritance_chain
|
|
Build a chain and resolve an inherited level.
|
|
turtle_validate
|
|
Validate ``docs/ontology/uko.ttl`` and verify zero errors.
|
|
universal_view
|
|
Verify all Layer 1 classes chain to ``uko:InformationUnit``.
|
|
list_all_domains
|
|
List all registered domains and print summary.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Ensure src/ is on the path so domain models can be imported.
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
from cleveragents.domain.models.acms.ontology_registry import ( # noqa: E402
|
|
build_detail_map_chain,
|
|
get_domain,
|
|
get_layer1_domains,
|
|
list_domains,
|
|
validate_turtle_file,
|
|
)
|
|
|
|
_PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def _domain_lookup() -> int:
|
|
"""Look up every registered domain and print summary."""
|
|
expected = {
|
|
"uko:": ("https://cleveragents.ai/ontology/uko#", 0, 5),
|
|
"uko-code:": ("https://cleveragents.ai/ontology/uko/code#", 1, 5),
|
|
"uko-doc:": ("https://cleveragents.ai/ontology/uko/doc#", 1, 17),
|
|
"uko-data:": ("https://cleveragents.ai/ontology/uko/data#", 1, 13),
|
|
"uko-infra:": ("https://cleveragents.ai/ontology/uko/infra#", 1, 7),
|
|
}
|
|
for prefix, (iri, layer, cls_count) in expected.items():
|
|
desc = get_domain(prefix)
|
|
assert desc.iri == iri, f"{prefix}: IRI mismatch"
|
|
assert desc.layer == layer, f"{prefix}: layer mismatch"
|
|
assert len(desc.classes) == cls_count, (
|
|
f"{prefix}: expected {cls_count} classes, got {len(desc.classes)}"
|
|
)
|
|
print(f"OK {prefix} -> {iri} (layer={layer}, classes={cls_count})")
|
|
print("DOMAIN_LOOKUP_PASSED")
|
|
return 0
|
|
|
|
|
|
def _detail_level_resolution() -> int:
|
|
"""Resolve key levels for every Layer 1 domain."""
|
|
checks: list[tuple[str, str, int]] = [
|
|
("uko-code:", "MODULE_LISTING", 0),
|
|
("uko-code:", "FULL_SOURCE", 9),
|
|
("uko-code:", "SIGNATURES", 4),
|
|
("uko-doc:", "TITLE_ONLY", 0),
|
|
("uko-doc:", "FULL_CONTENT", 10),
|
|
("uko-doc:", "TOPIC_SENTENCES", 6),
|
|
("uko-data:", "SCHEMA_LISTING", 0),
|
|
("uko-data:", "FULL_CATALOG", 11),
|
|
("uko-data:", "TYPED_COLUMNS", 3),
|
|
("uko-infra:", "SERVICE_LISTING", 0),
|
|
("uko-infra:", "WITH_DEPLOYMENT", 8),
|
|
("uko-infra:", "CONFIG_KEYS", 4),
|
|
]
|
|
for prefix, level, expected in checks:
|
|
desc = get_domain(prefix)
|
|
actual = desc.detail_map.resolve(level)
|
|
assert actual == expected, (
|
|
f"{prefix}.resolve({level!r}) = {actual}, expected {expected}"
|
|
)
|
|
print(f"OK {prefix} {level} -> {actual}")
|
|
print("DETAIL_LEVEL_RESOLUTION_PASSED")
|
|
return 0
|
|
|
|
|
|
def _inheritance_chain() -> int:
|
|
"""Build a chain from uko-code: and verify inherited levels."""
|
|
chain = build_detail_map_chain("uko-code:")
|
|
assert chain.resolve("MODULE_LISTING") == 0
|
|
assert chain.resolve("FULL_SOURCE") == 9
|
|
assert chain.max_depth == 9
|
|
print("OK chain resolves inherited levels correctly")
|
|
print("INHERITANCE_CHAIN_PASSED")
|
|
return 0
|
|
|
|
|
|
def _turtle_validate() -> int:
|
|
"""Validate the project ontology file."""
|
|
ttl_path = _PROJECT_ROOT / "docs" / "ontology" / "uko.ttl"
|
|
errors = validate_turtle_file(ttl_path)
|
|
if errors:
|
|
for err in errors:
|
|
print(f"ERROR: {err}", file=sys.stderr)
|
|
return 1
|
|
print(f"OK {ttl_path} passed Turtle validation (0 errors)")
|
|
print("TURTLE_VALIDATE_PASSED")
|
|
return 0
|
|
|
|
|
|
def _universal_view() -> int:
|
|
"""Verify all Layer 1 domains have depth 0 resolving to 0."""
|
|
for desc in get_layer1_domains():
|
|
actual = desc.detail_map.resolve(0)
|
|
assert actual == 0, f"{desc.prefix} resolved depth 0 to {actual}, expected 0"
|
|
print(f"OK {desc.prefix} depth 0 -> 0")
|
|
print("UNIVERSAL_VIEW_PASSED")
|
|
return 0
|
|
|
|
|
|
def _list_all_domains() -> int:
|
|
"""List all registered domains with summary."""
|
|
domains = list_domains()
|
|
assert len(domains) == 5, f"Expected 5 domains, got {len(domains)}"
|
|
for d in domains:
|
|
levels = d.detail_map.effective_levels()
|
|
print(
|
|
f" {d.prefix:<14} layer={d.layer} "
|
|
f"classes={len(d.classes):<3} levels={len(levels)}"
|
|
)
|
|
print("LIST_ALL_DOMAINS_PASSED")
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
"""Dispatch to the requested command."""
|
|
if len(sys.argv) < 2:
|
|
print(f"Usage: {sys.argv[0]} <command>", file=sys.stderr)
|
|
return 1
|
|
|
|
cmd = sys.argv[1]
|
|
dispatch = {
|
|
"domain_lookup": _domain_lookup,
|
|
"detail_level_resolution": _detail_level_resolution,
|
|
"inheritance_chain": _inheritance_chain,
|
|
"turtle_validate": _turtle_validate,
|
|
"universal_view": _universal_view,
|
|
"list_all_domains": _list_all_domains,
|
|
}
|
|
handler = dispatch.get(cmd)
|
|
if handler is None:
|
|
print(f"Unknown command: {cmd}", file=sys.stderr)
|
|
return 1
|
|
return handler()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|