- docs/reference/plan_cli.md: add note about legacy/v3 plan workflow mixing being disallowed (introduced in v3.8.0, issue #1577) - docs/reference/uko_runtime.md: document v3.8.0 provenance tracking (sourceResource, validFrom, isCurrent on typed triples) and revision chain for temporal queries across indexing runs (issue #891) - docs/reference/decision_correction.md: add CorrectionAttemptRecord section documenting the correction_attempts table, state lifecycle, repository API, and usage examples (issue #920) - docs/modules/uko-provenance.md: new module guide for UKO provenance tracking covering purpose, how provenance is attached, revision chain mechanics, query patterns, persistence format, BDD coverage, and gotchas
10 KiB
UKO Runtime Services
This document covers the three runtime services that operationalize the
Universal Knowledge Ontology (UKO) within the ACMS context pipeline.
These services were introduced in v3.7.0 (issue #891) and extended in
v3.8.0 (issue #891) with provenance tracking and temporal versioning.
They implement the runtime requirements from docs/specification.md
§185, §20568, §43924.
For the ontology structure itself, see uko.md.
For the indexer that populates the graph, see uko_indexer.md.
For the temporal data model, see temporal_data_model.md.
For the dedicated provenance module guide, see ../modules/uko-provenance.md.
Overview
The three runtime services work together as follows:
UKOIndexer.index_graph()
│
├── UKOInferenceEngine.infer() ← adds implicit triples (confidence 0.7)
│
├── ProvenanceMetadata attached ← sourceResource, validFrom, isCurrent (v3.8.0+)
│
└── GraphIndexBackend ← stores all triples (explicit + implicit)
│
├── UKOQueryInterface ← ACMS context strategies query here
│
├── UKOGraphPersistence ← serialise/restore across restarts
│
└── RevisionChain ← tracks ontology state across indexing runs (v3.8.0+)
Provenance Tracking (v3.8.0+)
Every typed triple produced by UKOIndexer.index_graph() now carries
provenance metadata. This enables temporal queries over historical UKO
snapshots and supports audit trails for context decisions.
Provenance Fields on Typed Triples
| Field | OWL Property | Description |
|---|---|---|
sourceResource |
uko:sourceResource |
ULID of the CleverAgents resource that produced this triple |
validFrom |
uko:validFrom |
UTC timestamp when this triple version became valid |
isCurrent |
uko:isCurrent |
Whether this is the current (non-superseded) version of the triple |
When a resource is re-indexed, the previous triples for that resource are
marked isCurrent=False and validUntil is set to the re-indexing
timestamp. New triples are created with isCurrent=True and a fresh
validFrom.
Revision Chain
A revision chain tracks the full history of ontology state across indexing runs. Each indexing run creates a new revision entry linked to the previous one, enabling point-in-time queries:
from cleveragents.application.services.uko_persistence import UKOGraphPersistence
persistence = UKOGraphPersistence(
graph_backend=backend,
project="local/my-app",
persist_path=Path("~/.config/cleveragents/uko-graph.json").expanduser(),
)
# Query triples valid at a specific point in time
historical_triples = persistence.query_at_time(
timestamp=datetime(2026, 3, 15, tzinfo=timezone.utc)
)
Temporal Query Patterns
| Query | Description |
|---|---|
isCurrent=True |
Current (hot-tier) triples only |
validFrom <= T < validUntil |
Triples valid at timestamp T |
sourceResource = ULID |
All triples from a specific resource |
| All triples | Full historical graph (cold-tier) |
UKOQueryInterface
Module: cleveragents.application.services.uko_query_interface
Provides ACMS context strategies with a typed interface to the UKO knowledge graph. Strategies use this to discover resource types, ontology layers, and implicit relationships without constructing raw SPARQL queries.
Constructor
| Parameter | Type | Required | Description |
|---|---|---|---|
graph_backend |
GraphIndexBackend |
Yes | Graph index backend to query |
project |
str |
Yes | Namespaced project name (e.g. "local/my-app") |
Raises TypeError if graph_backend does not satisfy GraphIndexBackend.
Raises ValueError if project is empty or whitespace-only.
ClassificationResult
Frozen dataclass returned by classify_resource().
| Field | Type | Description |
|---|---|---|
resource_id |
str |
ULID of the classified resource |
layer |
int |
Highest UKO layer populated for this resource (0–3) |
primary_type |
str |
Primary UKO type URI (e.g. uko-py:Module) |
all_types |
tuple[str, ...] |
All UKO type URIs found for this resource |
implicit_relations |
tuple[tuple[str, str, str], ...] |
Inferred (subject, predicate, object) triples |
Layer constants:
| Constant | Value | Description |
|---|---|---|
LAYER_UNIVERSAL |
0 |
Foundation concepts |
LAYER_DOMAIN |
1 |
Software, documents, data schemas, infrastructure |
LAYER_PARADIGM |
2 |
OO, functional, procedural, markdown |
LAYER_TECHNOLOGY |
3 |
Python, TypeScript, Rust, Java, PostgreSQL |
Methods
classify_resource(resource_id: str) → ClassificationResult
Queries the graph backend for all triples associated with the given resource and extracts type, layer, and relationship data.
Returns a default ClassificationResult (layer 0, no types) if the resource
has not been indexed. Raises ValueError if resource_id is empty.
get_resources_by_layer(layer: int) → list[str]
Returns resource ULIDs classified at the given ontology layer (0–3).
Raises ValueError if layer is outside 0–3.
get_implicit_relations(resource_id: str) → list[tuple[str, str, str]]
Returns implicit relationships inferred for a resource as a list of
(subject, predicate, object) tuples. Raises ValueError if
resource_id is empty.
Usage Example
from cleveragents.application.services.uko_query_interface import (
UKOQueryInterface,
LAYER_TECHNOLOGY,
)
query = UKOQueryInterface(graph_backend=backend, project="local/my-app")
# Classify a resource
result = query.classify_resource("01HXYZ...")
print(result.layer) # e.g. 3 (Technology)
print(result.primary_type) # e.g. "uko-py:Module"
print(result.all_types) # all UKO type URIs
# Find all Python-layer resources
python_resources = query.get_resources_by_layer(LAYER_TECHNOLOGY)
# Get inferred relationships
relations = query.get_implicit_relations("01HXYZ...")
for subject, predicate, obj in relations:
print(f"{subject} --[{predicate}]--> {obj}")
UKOInferenceEngine
Module: cleveragents.application.services.uko_inference
Analyses UKO triples produced by domain analyzers and generates additional triples representing inferred semantic relationships. Inferred triples are stored with a confidence score of 0.7 to distinguish them from deterministic extractions.
Three inference patterns are applied:
| Pattern | Predicate | Condition |
|---|---|---|
| Co-occurrence | uko:implicitSiblingOf |
Two subjects share the same rdf:type |
| Containment | uko:implicitContains |
Subject URI is a prefix of another subject's URI |
| Dependency | uko:implicitDependsOn |
Subject references another subject's URI in its object values |
Methods
infer(triples: Sequence[UKOTriple]) → list[UKOTriple]
Analyses the provided triples and returns a list of inferred implicit
triples. The returned triples have confidence=0.7.
Integration with UKOIndexer
UKOIndexer.index_graph() automatically calls UKOInferenceEngine.infer()
after the domain analyzer produces triples, then stores both the original
and inferred triples in the graph backend.
from cleveragents.application.services.uko_inference import UKOInferenceEngine
engine = UKOInferenceEngine()
implicit_triples = engine.infer(original_triples)
# implicit_triples[0].confidence == 0.7
UKOGraphPersistence
Module: cleveragents.application.services.uko_persistence
Serialises the in-memory UKO graph (triples stored in a
GraphIndexBackend) to a JSON file and restores it on application restart.
This satisfies the acceptance criterion: "UKO data persists across
application restarts."
Persistence Format
{
"version": "1",
"project": "local/my-app",
"triples": [
{"subject": "...", "predicate": "...", "object": "..."}
]
}
UKOPersistenceBackend Protocol
Custom persistence backends must implement:
class UKOPersistenceBackend(Protocol):
def save(self, data: dict[str, object]) -> None: ...
def load(self) -> dict[str, object] | None: ...
The default implementation writes to a JSON file. An in-memory backend is provided for testing.
UKOGraphPersistence
| Parameter | Type | Required | Description |
|---|---|---|---|
graph_backend |
GraphIndexBackend |
Yes | Backend holding the live graph |
project |
str |
Yes | Namespaced project name |
backend |
UKOPersistenceBackend | None |
No | Persistence backend (default: JSON file) |
persist_path |
Path | None |
No | Path for the JSON file backend |
save() → None
Serialises all triples from the graph backend to the persistence store.
load() → bool
Restores triples from the persistence store into the graph backend.
Returns True if data was loaded, False if no persisted data exists.
Usage Example
from pathlib import Path
from cleveragents.application.services.uko_persistence import UKOGraphPersistence
persistence = UKOGraphPersistence(
graph_backend=backend,
project="local/my-app",
persist_path=Path("~/.config/cleveragents/uko-graph.json").expanduser(),
)
# On shutdown — save the graph
persistence.save()
# On startup — restore the graph
loaded = persistence.load()
if loaded:
print("UKO graph restored from disk")
Layer URI Prefix Mapping
The _infer_layer_from_uri() helper (used internally by UKOQueryInterface)
maps type URIs to layer numbers:
| Prefix | Layer |
|---|---|
uko: / https://cleveragents.ai/ontology/uko# |
0 (Universal) |
uko-code:, uko-doc:, uko-data:, uko-infra: |
1 (Domain) |
uko-oo:, uko-func:, uko-proc: |
2 (Paradigm) |
uko-py:, uko-ts:, uko-rs:, uko-java: |
3 (Technology) |
Related Documentation
- UKO Ontology — four-layer ontology structure and URI conventions
- UKO Indexer — real-time index synchronization
- Temporal Data Model — revision-aware RDF and three-tier storage
- UKO Provenance Module — provenance tracking and temporal versioning guide
- ACMS — Advanced Context Management System overview
- ACMS Fusion — Fragment Fusion pipeline (Phase 2 protocols)