Session File Format (.uyava)
This page defines the .uyava wire format for replay files.
Container
- File extension:
.uyava - Content: NDJSON (
UTF-8, one JSON object per line) - Recommended order:
sessionHeader- event records
- optional marker records
- Desktop replay compatibility:
gzipor plain NDJSON (none).
Record kinds
Each NDJSON line is one record. Supported kinds:
- Header record:
type: "sessionHeader"(orrecordType: "header") - Event record:
recordType: "event"(or omitted) - Marker record:
recordType: "marker"ortype: "_marker"
If recordType is omitted and type is not sessionHeader/_marker, the line is treated as an event.
Header record
Required:
type:"sessionHeader"sessionId: stringstartedAt: ISO-8601 timestamp
Versioning:
formatVersion(preferred) andschemaVersion(legacy alias) are both read- current supported value:
1 - values
> 1are rejected by Desktop replay
Optional metadata:
compression:"gzip"|"none"|"zstd"(for Desktop replay files, usegzipornone)app:{ "name"?, "version"?, "build"? }platform:{ "os"?, "version"?, "timezone"? }reason: stringredaction:{ redactionApplied, allowRawData?, maskFields?, dropFields?, tagsAllowList?, tagsDenyList? }hostMetadata: objectrecorder: object
Event envelope
Canonical shape:
{
"recordType": "event",
"type": "replaceGraph",
"timestamp": "2026-03-06T13:17:34.282591Z",
"monotonicMicros": 22613,
"scope": "realtime",
"sequenceId": "optional",
"payload": {}
}
Fields:
type(required): event type stringpayload(required): event payload objecttimestamp(recommended): ISO-8601 timestampmonotonicMicros(recommended): microseconds since session start- legacy fallback:
timestampMicros - if both are missing, value becomes
0
- legacy fallback:
scope(optional):snapshot|realtime|diagnosticsequenceId(optional): stringredactedKeys(optional): string[]hostMetadata(optional): object
Graph payload contracts
Node object (nodes[], addNode, patchNode.node)
Required:
id: string
Canonical/recommended:
type: string ("unknown"if omitted)label: string (falls back toidif omitted/empty)
Optional:
description: stringparentId: stringtags: string[]tagsNormalized: string[]tagsCatalog: string[]color: normalized hex colorcolorPriorityIndex: intshape: stringlifecycle:unknown | initialized | disposedinitSource: string
Modeling note: the format allows a single global root node, but this is discouraged for real graphs. A synthetic root with all nodes under it usually reduces readability and increases visual density. Prefer several meaningful top-level roots.
Edge object (edges[], addEdge, patchEdge.edge)
Required:
id: stringsource: string (node id)target: string (node id)
Optional:
label: stringdescription: stringremapped: booleanbidirectional: boolean
For graph snapshots/updates, use source/target (not from/to).
Supported event types
replaceGraph
Replaces graph state.
Payload:
nodes: node[]edges: edge[]metrics(optional): metric definition[]eventChains(optional): event-chain definition[]sourceId/sourceType(optional): ingest metadata
loadGraph
Merges graph data into current state.
Payload:
nodes(optional): node[]edges(optional): edge[]
addNode
Payload: single node object.
addEdge
Payload: single edge object.
removeNode
Payload:
id: node idcascadeEdgeIds(optional): string[]
removeEdge
Payload:
id: edge id
patchNode
Payload:
id(recommended): node idnode: full node object snapshotchangedKeys(optional): string[]
patchEdge
Payload:
id(recommended): edge idedge: full edge object snapshot (withsource/target)changedKeys(optional): string[]
edgeEvent (and legacy alias animation)
Payload:
message: non-empty string (required for render/journal)- either:
from+to, oredge(resolved to endpoints from known edges)
severity(optional):trace|debug|info|warn|error|fataltimestamp(optional): ISO-8601sourceRef/sourceId/sourceType(optional)isolateId/isolateName/isolateNumber(optional)
nodeEvent
Payload:
nodeId: string (required)message: string (recommended; defaults to"node event"if missing/empty)severity(optional):trace|debug|info|warn|error|fataltags(optional): string[]timestamp(optional): ISO-8601sourceRef/sourceId/sourceType(optional)isolateId/isolateName/isolateNumber(optional)payload(optional): object for nested data
Nested metric sample inside nodeEvent.payload:
{
"metric": {
"id": "checkout_duration_ms",
"value": 1529.0,
"timestamp": "2026-03-06T13:17:35.813290Z"
}
}
Nested event-chain progress inside nodeEvent.payload:
{
"chain": {
"id": "checkout_flow",
"step": "place_order",
"attempt": "attempt-1",
"status": "failed"
},
"edgeId": "e75"
}
Notes:
- chain object requires
idandstep attemptis optional- failure is detected when status is
"failed"or"failure" - legacy fallback: if
chain.statusis missing, top-levelpayload.statusis used
nodeLifecycle
Payload:
nodeId: stringstate:initialized | disposed | unknown
defineMetric
Payload:
id: string (required)label(optional)description(optional)unit(optional)tags(optional): string[]tagsNormalized(optional): string[]aggregators(optional):last|min|max|sum|count[]- defaults to
["last"]if missing/invalid
- defaults to
defineEventChain
Payload:
id: string (required)- at least one tag:
tags: string[] (preferred), ortag: string (legacy)
label(optional; defaults toid)description(optional)tagsNormalized(optional)tagsCatalog(optional)steps: step[] (required)
Step object:
stepId: string (required)nodeId: string (required)edgeId: string (optional)expectedSeverity:trace|debug|info|warn|error|fatal(optional)
graphDiagnostics
Payload:
code: string (required)level:info|warning|error(required)codeEnum(optional)nodeId(optional)edgeId(optional)context(optional): objecttimestamp(optional): ISO-8601
clearDiagnostics
Payload: empty object {} (recommended).
Marker record (optional)
Marker shape:
{
"recordType": "marker",
"type": "_marker",
"id": "checkpoint-1",
"label": "Payment failed",
"timestamp": "2026-03-06T13:17:35.813365Z",
"offsetMicros": 1553387,
"kind": "error",
"level": "warn",
"meta": { "requestId": "r-42" }
}
Core marker fields:
idlabeltimestampoffsetMicros
Minimal valid file
{"type":"sessionHeader","formatVersion":1,"schemaVersion":1,"sessionId":"demo-001","startedAt":"2026-03-06T13:17:34.259978Z","compression":"none"}
{"recordType":"event","type":"replaceGraph","timestamp":"2026-03-06T13:17:34.282591Z","monotonicMicros":22613,"scope":"snapshot","payload":{"nodes":[{"id":"a","type":"screen","label":"A"}],"edges":[]}}
{"recordType":"event","type":"nodeEvent","timestamp":"2026-03-06T13:17:34.313886Z","monotonicMicros":53908,"scope":"realtime","payload":{"nodeId":"a","message":"opened","severity":"info"}}
Validation checklist
- NDJSON only: one JSON object per line.
- Include exactly one
sessionHeader. - Use
formatVersion: 1(andschemaVersion: 1for compatibility). - Keep
monotonicMicrosnon-negative and monotonic. - For graph edges in snapshots/updates use
source/target. - For
edgeEvent, include non-emptymessageand valid endpoints (from/toor resolvableedge). - Avoid a synthetic single global root parent for all nodes; prefer domain/feature top-level roots for better replay readability.