Files
freemo 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: update and extend documentation for v3.8.0 changes
- 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
2026-04-05 20:05:48 +00:00

308 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (03) |
| `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 (03).
Raises `ValueError` if `layer` is outside 03.
#### `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)