Files
wifi-densepose/npm/packages/ruvector-extensions/docs/TEMPORAL.md
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

17 KiB

Temporal Tracking Module

Complete version control and time-travel capabilities for RUVector database evolution.

Overview

The Temporal Tracking module provides enterprise-grade version management for your vector database, enabling:

  • Version Control: Create snapshots of database state over time
  • Change Tracking: Track all modifications with full audit trail
  • Time-Travel Queries: Query database at any point in history
  • Diff Generation: Compare versions to see what changed
  • Revert Capability: Safely rollback to previous states
  • Visualization Data: Generate timeline and change frequency data
  • Delta Encoding: Efficient storage using incremental changes
  • Event System: React to changes with event listeners

Installation

npm install ruvector-extensions

Quick Start

import { TemporalTracker, ChangeType } from 'ruvector-extensions';

const tracker = new TemporalTracker();

// Track a change
tracker.trackChange({
  type: ChangeType.ADDITION,
  path: 'nodes.User',
  before: null,
  after: { name: 'User', properties: ['id', 'name', 'email'] },
  timestamp: Date.now()
});

// Create version
const version = await tracker.createVersion({
  description: 'Initial schema',
  tags: ['v1.0', 'production']
});

// Query past state
const pastState = await tracker.queryAtTimestamp(version.timestamp);

// Compare versions
const diff = await tracker.compareVersions(v1.id, v2.id);

Core Concepts

Change Types

Four types of changes are tracked:

enum ChangeType {
  ADDITION = 'addition',       // New entity added
  DELETION = 'deletion',       // Entity removed
  MODIFICATION = 'modification', // Entity changed
  METADATA = 'metadata'        // Metadata updated
}

Path System

Changes are organized by path (dot-notation):

'nodes.User'              // User node type
'edges.FOLLOWS'           // FOLLOWS edge type
'config.maxUsers'         // Configuration value
'schema.version'          // Schema version
'nodes.User.properties'   // Nested property

Delta Encoding

Only differences between versions are stored:

Baseline (v0): {}
  ↓ + Change 1: Add User node
V1: { nodes: { User: {...} } }
  ↓ + Change 2: Add Post node
V2: { nodes: { User: {...}, Post: {...} } }

API Reference

TemporalTracker Class

Constructor

const tracker = new TemporalTracker();

Creates a new tracker with a baseline version.

trackChange(change: Change): void

Track a change to be included in the next version.

tracker.trackChange({
  type: ChangeType.ADDITION,
  path: 'nodes.User',
  before: null,
  after: { name: 'User', properties: ['id', 'name'] },
  timestamp: Date.now(),
  metadata: { author: 'system' } // optional
});

Parameters:

  • type: Type of change (ADDITION, DELETION, MODIFICATION, METADATA)
  • path: Dot-notation path to the changed entity
  • before: Previous value (null for additions)
  • after: New value (null for deletions)
  • timestamp: When the change occurred
  • metadata: Optional metadata about the change

Events: Emits changeTracked event

createVersion(options: CreateVersionOptions): Promise

Create a new version with all pending changes.

const version = await tracker.createVersion({
  description: 'Added user authentication',
  tags: ['v2.0', 'production'],
  author: 'developer@example.com',
  metadata: { ticket: 'FEAT-123' }
});

Parameters:

  • description: Human-readable description (required)
  • tags: Array of tags for categorization
  • author: Who created this version
  • metadata: Additional custom metadata

Returns: Version object with ID, timestamp, changes, checksum

Events: Emits versionCreated event

listVersions(tags?: string[]): Version[]

List all versions, optionally filtered by tags.

// All versions
const allVersions = tracker.listVersions();

// Only production versions
const prodVersions = tracker.listVersions(['production']);

// Multiple tags (OR logic)
const tagged = tracker.listVersions(['v1.0', 'v2.0']);

Returns: Array of versions, sorted newest first

getVersion(versionId: string): Version | null

Get a specific version by ID.

const version = tracker.getVersion('version-id-here');
if (version) {
  console.log(version.description);
  console.log(version.changes.length);
}

compareVersions(fromId, toId): Promise

Generate a diff between two versions.

const diff = await tracker.compareVersions(v1.id, v2.id);

console.log('Summary:', diff.summary);
// { additions: 5, deletions: 2, modifications: 3 }

diff.changes.forEach(change => {
  console.log(`${change.type} at ${change.path}`);
  if (change.type === ChangeType.MODIFICATION) {
    console.log(`  Before: ${change.before}`);
    console.log(`  After: ${change.after}`);
  }
});

Returns: VersionDiff with:

  • fromVersion: Source version ID
  • toVersion: Target version ID
  • changes: Array of changes
  • summary: Count of additions/deletions/modifications

revertToVersion(versionId: string): Promise

Revert to a previous version (creates new version with inverse changes).

// Revert to v1 state
const revertVersion = await tracker.revertToVersion(v1.id);

console.log('Created revert version:', revertVersion.id);
console.log('Description:', revertVersion.description);
// "Revert to version: {original description}"

Important: This creates a NEW version with inverse changes, preserving history.

Events: Emits versionReverted event

queryAtTimestamp(timestamp | options): Promise

Perform a time-travel query to get database state at a specific point.

// Query at specific timestamp
const yesterday = Date.now() - 86400000;
const pastState = await tracker.queryAtTimestamp(yesterday);

// Query at specific version
const stateAtV1 = await tracker.queryAtTimestamp({
  versionId: v1.id
});

// Query with filters
const userNodesOnly = await tracker.queryAtTimestamp({
  timestamp: Date.now(),
  pathPattern: /^nodes\.User/,  // Only User nodes
  includeMetadata: true
});

Options:

  • timestamp: Unix timestamp
  • versionId: Specific version to query
  • pathPattern: RegExp to filter paths
  • includeMetadata: Include metadata in results

Returns: Reconstructed state object

addTags(versionId: string, tags: string[]): void

Add tags to an existing version.

tracker.addTags(version.id, ['stable', 'tested', 'production']);

Tags are useful for:

  • Release marking (v1.0, v2.0)
  • Environment (production, staging)
  • Status (stable, experimental)
  • Features (auth-enabled, new-ui)

getVisualizationData(): VisualizationData

Get data for visualizing change history.

const vizData = tracker.getVisualizationData();

// Timeline of all versions
vizData.timeline.forEach(item => {
  console.log(`${new Date(item.timestamp).toISOString()}`);
  console.log(`  ${item.description}`);
  console.log(`  Changes: ${item.changeCount}`);
});

// Change frequency over time
vizData.changeFrequency.forEach(({ timestamp, count, type }) => {
  console.log(`${timestamp}: ${count} ${type} changes`);
});

// Most frequently changed paths
vizData.hotspots.forEach(({ path, changeCount }) => {
  console.log(`${path}: ${changeCount} changes`);
});

// Version graph (for D3.js, vis.js, etc.)
const graph = vizData.versionGraph;
// graph.nodes: [{ id, label, timestamp }]
// graph.edges: [{ from, to }]

Returns: VisualizationData with:

  • timeline: Chronological version list
  • changeFrequency: Changes over time
  • hotspots: Most modified paths
  • versionGraph: Parent-child relationships

getAuditLog(limit?: number): AuditLogEntry[]

Get audit trail of all operations.

const recentLogs = tracker.getAuditLog(50);

recentLogs.forEach(entry => {
  console.log(`[${entry.operation}] ${entry.status}`);
  console.log(`  By: ${entry.actor || 'system'}`);
  console.log(`  Details:`, entry.details);
  if (entry.error) {
    console.log(`  Error: ${entry.error}`);
  }
});

Returns: Array of audit entries, newest first

pruneVersions(keepCount, preserveTags?): void

Delete old versions to save space.

// Keep last 10 versions + tagged ones
tracker.pruneVersions(10, ['baseline', 'production', 'stable']);

Parameters:

  • keepCount: Number of recent versions to keep
  • preserveTags: Tags to always preserve

Safety: Never deletes versions with dependencies

exportBackup(): BackupData

Export all data for backup.

const backup = tracker.exportBackup();

// Save to file
import { writeFileSync } from 'fs';
writeFileSync('backup.json', JSON.stringify(backup));

console.log(`Backed up ${backup.versions.length} versions`);
console.log(`Exported at: ${new Date(backup.exportedAt).toISOString()}`);

Returns:

  • versions: All version objects
  • auditLog: Complete audit trail
  • currentState: Current database state
  • exportedAt: Export timestamp

importBackup(backup: BackupData): void

Import data from backup.

import { readFileSync } from 'fs';

const backup = JSON.parse(readFileSync('backup.json', 'utf8'));
tracker.importBackup(backup);

console.log('Backup restored successfully');

Warning: Clears all existing data before import

getStorageStats(): StorageStats

Get storage statistics.

const stats = tracker.getStorageStats();

console.log(`Versions: ${stats.versionCount}`);
console.log(`Changes: ${stats.totalChanges}`);
console.log(`Audit entries: ${stats.auditLogSize}`);
console.log(`Estimated size: ${(stats.estimatedSizeBytes / 1024).toFixed(2)} KB`);
console.log(`Date range: ${new Date(stats.oldestVersion).toISOString()} to ${new Date(stats.newestVersion).toISOString()}`);

Event System

The tracker is an EventEmitter with the following events:

versionCreated

Emitted when a new version is created.

tracker.on('versionCreated', (version: Version) => {
  console.log(`New version: ${version.id}`);
  console.log(`Changes: ${version.changes.length}`);

  // Send notification
  notificationService.send(`Version ${version.description} created`);
});

versionReverted

Emitted when reverting to a previous version.

tracker.on('versionReverted', (fromVersion: string, toVersion: string) => {
  console.log(`Reverted from ${fromVersion} to ${toVersion}`);

  // Log critical event
  logger.warn('Database reverted', { fromVersion, toVersion });
});

changeTracked

Emitted when a change is tracked.

tracker.on('changeTracked', (change: Change) => {
  console.log(`Change: ${change.type} at ${change.path}`);

  // Real-time monitoring
  monitoringService.trackChange(change);
});

auditLogged

Emitted when an audit entry is created.

tracker.on('auditLogged', (entry: AuditLogEntry) => {
  console.log(`Audit: ${entry.operation} - ${entry.status}`);

  // Send to external audit system
  auditSystem.log(entry);
});

error

Emitted on errors.

tracker.on('error', (error: Error) => {
  console.error('Tracker error:', error);

  // Error handling
  errorService.report(error);
});

Usage Patterns

Pattern 1: Continuous Development

Track changes as you develop, create versions at milestones.

// Development loop
function updateSchema(changes) {
  changes.forEach(change => tracker.trackChange(change));

  if (readyForRelease) {
    await tracker.createVersion({
      description: 'Release v2.1',
      tags: ['v2.1', 'production']
    });
  }
}

Pattern 2: Rollback Safety

Keep production-tagged versions for easy rollback.

// Before risky change
const safePoint = await tracker.createVersion({
  description: 'Safe point before migration',
  tags: ['production', 'safe-point']
});

try {
  // Risky operation
  performMigration();
} catch (error) {
  // Rollback on failure
  await tracker.revertToVersion(safePoint.id);
  console.log('Rolled back to safe state');
}

Pattern 3: Change Analysis

Analyze what changed between releases.

const prodVersions = tracker.listVersions(['production']);
const [current, previous] = prodVersions; // Newest first

const diff = await tracker.compareVersions(previous.id, current.id);

console.log('Changes in this release:');
console.log(`  Added: ${diff.summary.additions}`);
console.log(`  Modified: ${diff.summary.modifications}`);
console.log(`  Deleted: ${diff.summary.deletions}`);

// Generate changelog
const changelog = diff.changes.map(c =>
  `- ${c.type} ${c.path}`
).join('\n');

Pattern 4: Audit Compliance

Maintain complete audit trail for compliance.

// Track all changes with metadata
tracker.trackChange({
  type: ChangeType.MODIFICATION,
  path: 'sensitive.data',
  before: oldValue,
  after: newValue,
  timestamp: Date.now(),
  metadata: {
    user: currentUser.id,
    reason: 'GDPR request',
    ticket: 'LEGAL-456'
  }
});

// Export audit log monthly
const log = tracker.getAuditLog();
const monthlyLog = log.filter(e =>
  e.timestamp >= startOfMonth && e.timestamp < endOfMonth
);

saveAuditReport('audit-2024-01.json', monthlyLog);

Pattern 5: Time-Travel Debugging

Debug issues by examining past states.

// Find when bug was introduced
const versions = tracker.listVersions();

for (const version of versions) {
  const state = await tracker.queryAtTimestamp(version.timestamp);

  if (hasBug(state)) {
    console.log(`Bug present in version: ${version.description}`);
  } else {
    console.log(`Bug not present in version: ${version.description}`);

    // Compare with next version to find the change
    const nextVersion = versions[versions.indexOf(version) - 1];
    if (nextVersion) {
      const diff = await tracker.compareVersions(version.id, nextVersion.id);
      console.log('Changes that introduced bug:', diff.changes);
    }
    break;
  }
}

Best Practices

1. Meaningful Descriptions

// ❌ Bad
await tracker.createVersion({ description: 'Update' });

// ✅ Good
await tracker.createVersion({
  description: 'Add email verification to user registration',
  tags: ['feature', 'auth'],
  metadata: { ticket: 'FEAT-123' }
});

2. Consistent Tagging

// Establish tagging convention
const TAGS = {
  PRODUCTION: 'production',
  STAGING: 'staging',
  FEATURE: 'feature',
  BUGFIX: 'bugfix',
  HOTFIX: 'hotfix'
};

await tracker.createVersion({
  description: 'Fix critical auth bug',
  tags: [TAGS.HOTFIX, TAGS.PRODUCTION, 'v2.1.1']
});

3. Regular Pruning

// Prune monthly
setInterval(() => {
  tracker.pruneVersions(
    50, // Keep last 50 versions
    ['production', 'baseline', 'hotfix'] // Preserve important ones
  );
}, 30 * 24 * 60 * 60 * 1000); // 30 days

4. Backup Before Major Changes

async function majorMigration() {
  // Backup first
  const backup = tracker.exportBackup();
  await saveBackup('pre-migration.json', backup);

  // Create checkpoint
  const checkpoint = await tracker.createVersion({
    description: 'Pre-migration checkpoint',
    tags: ['checkpoint', 'migration']
  });

  // Perform migration
  try {
    await performMigration();
  } catch (error) {
    await tracker.revertToVersion(checkpoint.id);
    throw error;
  }
}

5. Use Events for Integration

// Integrate with monitoring
tracker.on('versionCreated', async (version) => {
  await metrics.increment('versions.created');
  await metrics.gauge('versions.total', tracker.listVersions().length);
});

// Integrate with notifications
tracker.on('versionReverted', async (from, to) => {
  await slack.send(`⚠️ Database reverted from ${from} to ${to}`);
});

Performance Considerations

Memory Usage

  • In-Memory Storage: All versions kept in memory
  • Recommendation: Prune old versions regularly
  • Large Databases: Consider periodic export/import

Query Performance

  • Time Complexity: O(n) where n = version chain length
  • Optimization: Keep version chains short with pruning
  • Path Filtering: O(1) lookup with path index

Storage Size

  • Delta Encoding: ~70-90% smaller than full snapshots
  • Compression: Use exportBackup() with external compression
  • Estimate: ~100 bytes per change on average

TypeScript Support

Full TypeScript definitions included:

import type {
  TemporalTracker,
  Change,
  ChangeType,
  Version,
  VersionDiff,
  AuditLogEntry,
  CreateVersionOptions,
  QueryOptions,
  VisualizationData
} from 'ruvector-extensions';

Examples

See /src/examples/temporal-example.ts for comprehensive examples covering:

  • Basic version management
  • Time-travel queries
  • Version comparison
  • Reverting
  • Visualization data
  • Audit logging
  • Storage management
  • Backup/restore
  • Event-driven architecture

Run examples:

npm run build
node dist/examples/temporal-example.js

License

MIT

Support