a0ac30d5de
CI / lint (pull_request) Successful in 21s
CI / typecheck (pull_request) Successful in 52s
CI / security (pull_request) Successful in 55s
CI / quality (pull_request) Successful in 39s
CI / build (pull_request) Successful in 29s
CI / helm (pull_request) Successful in 23s
CI / unit_tests (pull_request) Failing after 6m49s
CI / docker (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 17m22s
CI / integration_tests (pull_request) Failing after 23m1s
CI / coverage (pull_request) Successful in 11m3s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 56m57s
- 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
308 lines
10 KiB
Markdown
308 lines
10 KiB
Markdown
# 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`](uko.md).
|
||
For the indexer that populates the graph, see [`uko_indexer.md`](uko_indexer.md).
|
||
For the temporal data model, see [`temporal_data_model.md`](temporal_data_model.md).
|
||
For the dedicated provenance module guide, see [`../modules/uko-provenance.md`](../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:
|
||
|
||
```python
|
||
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
|
||
|
||
```python
|
||
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.
|
||
|
||
```python
|
||
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
|
||
|
||
```json
|
||
{
|
||
"version": "1",
|
||
"project": "local/my-app",
|
||
"triples": [
|
||
{"subject": "...", "predicate": "...", "object": "..."}
|
||
]
|
||
}
|
||
```
|
||
|
||
### UKOPersistenceBackend Protocol
|
||
|
||
Custom persistence backends must implement:
|
||
|
||
```python
|
||
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
|
||
|
||
```python
|
||
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](uko.md) — four-layer ontology structure and URI conventions
|
||
- [UKO Indexer](uko_indexer.md) — real-time index synchronization
|
||
- [Temporal Data Model](temporal_data_model.md) — revision-aware RDF and three-tier storage
|
||
- [UKO Provenance Module](../modules/uko-provenance.md) — provenance tracking and temporal versioning guide
|
||
- [ACMS](acms.md) — Advanced Context Management System overview
|
||
- [ACMS Fusion](acms_fusion.md) — Fragment Fusion pipeline (Phase 2 protocols)
|