Navigation & Time-Travel Queries
tnp intermediate 6 min read
ELI5
The navigator is a film editor who can jump the playhead to any timecode and show you exactly what the scene looked like at that moment — or cut between two timecodes to show only what changed.
Technical Deep Dive
Class Diagram
classDiagram class NavigationIndex { -node_to_timestamp: HashMap~NodeID, u64~ -timestamp_to_nodes: HashMap~u64, Vec~NodeID~~ +index_node(NodeID, u64) +get_timestamp(NodeID) Option~u64~ +nodes_at_timestamp(u64) Vec~NodeID~ } class TimelineNavigator { -index: NavigationIndex +index_timeline(timeline: &Timeline) +search_timestamp(timeline, target_ms) Result~Vec~NodeID~~ +state_at_time(timeline, timestamp_ms) Result~Vec~u8~~ +timeline_diff(timeline, start_ms, end_ms) Result~Vec~NodeID~~ +breadcrumb_trail(timeline) Vec~(u64, usize)~ } TimelineNavigator "1" --> "1" NavigationIndexindex_timeline
Iterates timeline.nodes in insertion order, reads each node’s wall-clock from timeline.node_timestamps, and writes both directions into NavigationIndex:
node_to_timestamp: NodeID → ms (for reverse lookup)timestamp_to_nodes: ms → Vec(for range queries)
Note: index_timeline must be called manually before using nodes_at_timestamp. There is no automatic sync.
State-at-Time Query
sequenceDiagram participant Caller participant Navigator as TimelineNavigator participant Timeline
Caller->>Navigator: state_at_time(timeline, ts_ms) Navigator->>Timeline: nodes_before_timestamp(ts_ms) Timeline-->>Navigator: Vec<NodeID> Navigator->>Navigator: XOR-fold bytes into 32-byte hash Navigator-->>Caller: Ok(Vec<u8>) — 32-byte state fingerprintUses the same XOR-fold as Timeline::state_hash but over a timestamp-filtered subset of nodes.
timeline_diff
pub fn timeline_diff(&self, timeline, start_ms, end_ms) -> Result<Vec<NodeID>, String> { let start_nodes = timeline.nodes_before_timestamp(start_ms)?; let end_nodes = timeline.nodes_before_timestamp(end_ms)?; Ok(end_nodes.iter().filter(|n| !start_nodes.contains(n)).cloned().collect())}Returns nodes that appear in the [0, end_ms] window but not in the [0, start_ms] window — i.e., operations applied between start_ms and end_ms.
Breadcrumb Trail
pub fn breadcrumb_trail(&self, timeline) -> Vec<(u64, usize)> { // One entry per distinct timestamp; value = cumulative node count before that tickEach element is (timestamp_ms, node_count_before). Useful for rendering a progress bar or timeline scrubber showing how many operations existed at each recorded moment.
Key Terms
- NavigationIndex → dual-direction timestamp↔NodeID map; must be explicitly populated via
index_timeline - state_at_time → 32-byte XOR fingerprint of all nodes before a timestamp; deterministic given same insertion order
- timeline_diff → nodes added between two timestamps; not a symmetric diff
- breadcrumb_trail → ordered
(ts, count)pairs for UI scrubbing
Q&A
Q: If two nodes are inserted at the same millisecond, does timestamp_to_nodes preserve both?
A: Yes — timestamp_to_nodes maps to Vec<NodeID>, so multiple nodes sharing a timestamp all appear under the same key.
Q: Does state_at_time return an error for an empty timeline?
A: No. nodes_before_timestamp returns Ok([]), and XOR-folding an empty list produces a 32-byte zero vector.
Q: Does breadcrumb_trail use NavigationIndex or read the Timeline directly?
A: It reads timeline.node_timestamps directly — the NavigationIndex is not used. The index field is populated separately and serves nodes_at_timestamp only.
Examples
let mut nav = TimelineNavigator::new();nav.index_timeline(&timeline);
// Reconstruct state hash at a specific momentlet hash = nav.state_at_time(&timeline, 1_700_000_000_000).unwrap();
// Find nodes added in a 5-second windowlet delta = nav.timeline_diff(&timeline, 1_700_000_000_000, 1_700_000_005_000).unwrap();
// Build a scrubber for the UIlet trail = nav.breadcrumb_trail(&timeline);// [(ts1, 0), (ts2, 1), (ts3, 2), ...]neighbors on the map
- Timeline & TimelineStatus Lifecycle checking whether a timeline counts toward the active_timelines stat
- Temporal DAG Data Model tracing why topological sort returns a cycle error
- Timeline Reconstruction implementing a new timeline UI control
- Hybrid Logical Clock deciding ordering between concurrent operations