Files
temp/docs/reference/temporal_data_model.md
eugen.thaci f66fb5a19a docs(spec): align ASCII UI tables in specification and related pages
Align Unicode box-drawing blocks and related tables in specification.md,
ADR-044/045/046, and reference pages for consistent MkDocs rendering.

ISSUES CLOSED: #1171
2026-04-03 04:55:21 +00:00

122 lines
5.1 KiB
Markdown

# Temporal Data Model (Revision-Aware RDF)
The Temporal Data Model enables revision tracking of UKO knowledge graph nodes
across three storage tiers (hot/warm/cold). When code changes, existing nodes
are **not deleted** -- they are marked historical and a new revision node is
created with a back-link to the predecessor.
Based on `docs/specification.md` lines 41940--42499.
## Architecture
```
Code Change ──► Analyzer ──► TemporalService.create_revision()
┌──────────┴───────────┐
│ TemporalBackend │
│ ┌─────────────────┐ │
│ │ Old node: │ │
│ │ isCurrent=false│ │
│ │ validUntil=now │ │
│ ├─────────────────┤ │
│ │ New node: │ │
│ │ isCurrent=true │ │
│ │ isRevisionOf= │ │
│ │ old_uri │ │
│ └─────────────────┘ │
└──────────────────────┘
```
## Domain Models
All models are frozen Pydantic `BaseModel` instances (immutable value objects).
### TemporalMetadata
Temporal fields carried by every UKO InformationUnit. Maps to the OWL
temporal properties defined in UKO Layer 0.
| Field | Type | Default | Spec Property |
|-------|------|---------|---------------|
| `valid_from` | `datetime` (UTC) | **required** | `uko:validFrom` |
| `valid_until` | `datetime \| None` | `None` | `uko:validUntil` |
| `is_current` | `bool` | `True` | `uko:isCurrent` |
| `is_revision_of` | `str \| None` | `None` | `uko:isRevisionOf` |
### TemporalNode
A UKO InformationUnit with full temporal metadata and provenance.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `node_uri` | `str` | **required** | Unique UKO URI (e.g., `uko-py:class/Auth_v2`) |
| `source_resource` | `str` | **required** | ULID of originating resource |
| `source_path` | `str` | **required** | File path within the resource |
| `source_range` | `str \| None` | `None` | Source range (e.g., `"15:1-87:0"`) |
| `temporal` | `TemporalMetadata` | **required** | Embedded temporal metadata |
### RevisionChain
Ordered chain of node versions for a single UKO concept.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `current_uri` | `str` | **required** | URI of the current head node |
| `predecessors` | `tuple[str, ...]` | `()` | Predecessor URIs (oldest-first) |
Properties: `depth` (total versions), `all_uris` (predecessors + current).
### TierRetentionConfig
Retention policy for warm and cold tiers.
| Field | Type | Default | Config Key |
|-------|------|---------|------------|
| `warm_retention_hours` | `int` (≥1) | `24` | `context.tiers.warm.retention-hours` |
| `cold_retention_days` | `int` (≥1) | `90` | `context.tiers.cold.retention-days` |
### TierQueryResult
Result from a tier-aware temporal query.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `nodes` | `tuple[TemporalNode, ...]` | `()` | Matching nodes |
| `tier` | `ContextTier` | **required** | HOT / WARM / COLD |
| `temporal_scope` | `TemporalScope` | **required** | CURRENT / RECENT / ALL |
## TemporalBackend Protocol
```python
class TemporalBackend(Protocol):
def store_node(self, node) -> None: ...
def create_revision(self, current_uri, new_node, timestamp) -> TemporalNode: ...
def get_current(self, node_uri_base) -> TemporalNode | None: ...
def get_history(self, node_uri_base, temporal_scope) -> tuple[TemporalNode, ...]: ...
def get_revision_chain(self, node_uri) -> RevisionChain: ...
def query_by_tier(self, tier, temporal_scope, retention) -> TierQueryResult: ...
def mark_historical(self, node_uri, timestamp) -> TemporalNode: ...
```
## Three Storage Tiers
| Tier | Content | Temporal Filter | Retention |
|------|---------|-----------------|-----------|
| **Hot** | Current UKO graph | `isCurrent = true` only | Until removed |
| **Warm** | Recent context | Current + recently-expired | `warm_retention_hours` (24h) |
| **Cold** | All historical | All temporal versions | `cold_retention_days` (90d) |
## Revision Chain Mechanics
1. Old node: `is_current``False`, `valid_until` → timestamp
2. New node: `is_current``True`, `valid_from` → timestamp
3. New node: `is_revision_of` → old node URI
4. Old node's `valid_from` is preserved unchanged
## v1 Limitations
- `InMemoryTemporalBackend` stores all nodes in a `dict`; no persistence.
- No SPARQL query helpers yet (deferred to graph backend integration).
- `temporal-archaeology` strategy stub exists but does not yet use the
temporal backend (wiring deferred to strategy integration milestone).