# The Semantic Request Graph
> The most important internal abstraction of Katra3D is not Wine objects,
> Vulkan objects, or D3D12 objects. It is a **semantic dependency graph**.
## Why
Frames, asset loads, and scene transitions are *flows*:
```text
READ asset.pak extent → GDEFLATE → UPLOAD texture → TRANSITION → DRAW → PRESENT
```
Each hop crosses layers. In the traditional stack each hop also crosses a
*boundary* — a server call, an FFI call, a translation, a wait. The graph
preserves **intent** so cross-layer optimization can act on the flow, not on
opaque lower-level operations:
* batch the three reads of a frame into one io_uring submission;
* prefetch the next extent while decompressing the current one;
* keep a staging buffer alive exactly until its GPU consumer signals;
* compute the critical path to the next present and protect it.
## Node kinds
`FileRead, MemoryMap, Decompress, Allocate, Upload, ResourceTransition,
Barrier, ShaderCompile, PipelineCreate, GpuCopy, GpuCompute, GpuGraphics,
GpuDraw, FenceWait, FenceSignal, Present, IoPrefetch, CacheLookup,
StagingReserve, SyncJoin`
## Edges
`Data` (producer→consumer data), `Control` (ordering), `Resource` (same
resource), `Fence` (fence/timeline order), `Sync` (generic).
## Metadata
Each node carries: label, producer request, consumer requests, latency,
cost units, confidence, deadline class (§15), epoch, and trace provenance
(the event seqs that produced it). Each allocation in `katra-memory` carries
the same provenance shape (§13):
```text
allocation:
producer = IoRequest(44291)
consumers = [Decompress(613), GpuCopy(889)]
recyclable_after = FenceEpoch(10122)
```
## Analysis
`katra-graph::analysis` implements CPM:
* `analyze` — earliest/latest start/finish and slack per node;
* `critical_path` — the weighted longest path (the answer to "why did this
frame cost what it cost");
* `cost_attribution` — kind-level cost for Pareto analysis.
The scheduler (`katra-schedule`) consumes the same analysis: topological
order, deadline priority, critical-path priority, and conservative
speculative handling. Every scheduling decision is recorded with its reason.
## Construction
Graphs are built from two sources, converging on the same runtime:
* **explicit intent** — the DirectStorage frontend (`katra-dstorage`)
turns `IDStorageQueue` requests into graph nodes;
* **inferred intent** — KatraFlow (`katra-flow`) observes ordinary reads and
predicts the next extent, becoming an `IoPrefetch` node with confidence.
Both feed `katra-io` + `katra-memory` + `katra-sync`. Investment in one
improves the other (§11).
## Rebuild from traces
`katra-replay::graph_builder` rebuilds a graph from a trace's causal links
(`causes` on events), so the critical path of a past session can be
inspected without re-running the game (§42). The demo receipt's critical
path (`file_read → decompress → upload → gpu_draw`) is a live example.