package ucxl import ( "fmt" "time" ) // TemporalNavigator handles temporal navigation operations within UCXL addresses type TemporalNavigator struct { // Navigation history for tracking traversal paths history []NavigationStep // Current position in version space currentVersion int maxVersion int // Version metadata versions map[int]VersionInfo } // NavigationStep represents a single step in temporal navigation history type NavigationStep struct { FromVersion int `json:"from_version"` ToVersion int `json:"to_version"` Operation string `json:"operation"` Timestamp time.Time `json:"timestamp"` Success bool `json:"success"` Error string `json:"error,omitempty"` } // VersionInfo contains metadata about a specific version type VersionInfo struct { Version int `json:"version"` Created time.Time `json:"created"` Author string `json:"author,omitempty"` Description string `json:"description,omitempty"` Tags []string `json:"tags,omitempty"` } // NavigationResult represents the result of a temporal navigation operation type NavigationResult struct { Success bool `json:"success"` TargetVersion int `json:"target_version"` PreviousVersion int `json:"previous_version"` VersionInfo *VersionInfo `json:"version_info,omitempty"` Error string `json:"error,omitempty"` } // TemporalConstraintError represents an error when temporal constraints are violated type TemporalConstraintError struct { Operation string `json:"operation"` RequestedStep int `json:"requested_step"` CurrentVersion int `json:"current_version"` MaxVersion int `json:"max_version"` Message string `json:"message"` } func (e TemporalConstraintError) Error() string { return fmt.Sprintf("temporal constraint violation: %s (current: %d, max: %d, requested: %d)", e.Message, e.CurrentVersion, e.MaxVersion, e.RequestedStep) } // NewTemporalNavigator creates a new temporal navigator func NewTemporalNavigator(maxVersion int) *TemporalNavigator { if maxVersion < 0 { maxVersion = 0 } return &TemporalNavigator{ history: make([]NavigationStep, 0), currentVersion: maxVersion, // Start at latest version maxVersion: maxVersion, versions: make(map[int]VersionInfo), } } // Navigate performs temporal navigation based on the temporal segment func (tn *TemporalNavigator) Navigate(segment TemporalSegment) (*NavigationResult, error) { previousVersion := tn.currentVersion var targetVersion int var err error step := NavigationStep{ FromVersion: previousVersion, Timestamp: time.Now(), Operation: segment.String(), } switch segment.Type { case TemporalLatest: targetVersion = tn.maxVersion err = tn.navigateToVersion(targetVersion) case TemporalAny: // For "any", we stay at current version (no navigation) targetVersion = tn.currentVersion case TemporalSpecific: targetVersion = segment.Count err = tn.navigateToVersion(targetVersion) case TemporalRelative: targetVersion, err = tn.navigateRelative(segment.Direction, segment.Count) default: err = fmt.Errorf("unknown temporal type: %v", segment.Type) } // Record the navigation step step.ToVersion = targetVersion step.Success = err == nil if err != nil { step.Error = err.Error() } tn.history = append(tn.history, step) result := &NavigationResult{ Success: err == nil, TargetVersion: targetVersion, PreviousVersion: previousVersion, } // Include version info if available if versionInfo, exists := tn.versions[targetVersion]; exists { result.VersionInfo = &versionInfo } if err != nil { result.Error = err.Error() } return result, err } // navigateToVersion navigates directly to a specific version func (tn *TemporalNavigator) navigateToVersion(version int) error { if version < 0 { return &TemporalConstraintError{ Operation: "navigate_to_version", RequestedStep: version, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "cannot navigate to negative version", } } if version > tn.maxVersion { return &TemporalConstraintError{ Operation: "navigate_to_version", RequestedStep: version, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "cannot navigate beyond latest version", } } tn.currentVersion = version return nil } // navigateRelative performs relative navigation (forward/backward) func (tn *TemporalNavigator) navigateRelative(direction Direction, count int) (int, error) { if count < 0 { return tn.currentVersion, &TemporalConstraintError{ Operation: fmt.Sprintf("navigate_relative_%s", direction), RequestedStep: count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "navigation count cannot be negative", } } var targetVersion int switch direction { case DirectionBackward: targetVersion = tn.currentVersion - count if targetVersion < 0 { return tn.currentVersion, &TemporalConstraintError{ Operation: "navigate_backward", RequestedStep: count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "cannot navigate before first version (version 0)", } } case DirectionForward: targetVersion = tn.currentVersion + count if targetVersion > tn.maxVersion { return tn.currentVersion, &TemporalConstraintError{ Operation: "navigate_forward", RequestedStep: count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "cannot navigate beyond latest version", } } default: return tn.currentVersion, fmt.Errorf("unknown navigation direction: %v", direction) } tn.currentVersion = targetVersion return targetVersion, nil } // GetCurrentVersion returns the current version position func (tn *TemporalNavigator) GetCurrentVersion() int { return tn.currentVersion } // GetMaxVersion returns the maximum available version func (tn *TemporalNavigator) GetMaxVersion() int { return tn.maxVersion } // SetMaxVersion updates the maximum version (e.g., when new versions are created) func (tn *TemporalNavigator) SetMaxVersion(maxVersion int) error { if maxVersion < 0 { return fmt.Errorf("max version cannot be negative") } tn.maxVersion = maxVersion // If current version is now beyond max, adjust it if tn.currentVersion > tn.maxVersion { tn.currentVersion = tn.maxVersion } return nil } // GetHistory returns the navigation history func (tn *TemporalNavigator) GetHistory() []NavigationStep { // Return a copy to prevent modification history := make([]NavigationStep, len(tn.history)) copy(history, tn.history) return history } // ClearHistory clears the navigation history func (tn *TemporalNavigator) ClearHistory() { tn.history = make([]NavigationStep, 0) } // GetLastNavigation returns the most recent navigation step func (tn *TemporalNavigator) GetLastNavigation() *NavigationStep { if len(tn.history) == 0 { return nil } last := tn.history[len(tn.history)-1] return &last } // SetVersionInfo sets metadata for a specific version func (tn *TemporalNavigator) SetVersionInfo(version int, info VersionInfo) { info.Version = version // Ensure consistency tn.versions[version] = info } // GetVersionInfo retrieves metadata for a specific version func (tn *TemporalNavigator) GetVersionInfo(version int) (*VersionInfo, bool) { info, exists := tn.versions[version] if exists { return &info, true } return nil, false } // GetAllVersions returns metadata for all known versions func (tn *TemporalNavigator) GetAllVersions() map[int]VersionInfo { // Return a copy to prevent modification result := make(map[int]VersionInfo) for k, v := range tn.versions { result[k] = v } return result } // CanNavigateBackward returns true if backward navigation is possible func (tn *TemporalNavigator) CanNavigateBackward(count int) bool { return tn.currentVersion-count >= 0 } // CanNavigateForward returns true if forward navigation is possible func (tn *TemporalNavigator) CanNavigateForward(count int) bool { return tn.currentVersion+count <= tn.maxVersion } // Reset resets the navigator to the latest version and clears history func (tn *TemporalNavigator) Reset() { tn.currentVersion = tn.maxVersion tn.ClearHistory() } // Clone creates a copy of the temporal navigator func (tn *TemporalNavigator) Clone() *TemporalNavigator { clone := &TemporalNavigator{ currentVersion: tn.currentVersion, maxVersion: tn.maxVersion, history: make([]NavigationStep, len(tn.history)), versions: make(map[int]VersionInfo), } // Copy history copy(clone.history, tn.history) // Copy version info for k, v := range tn.versions { clone.versions[k] = v } return clone } // ValidateTemporalSegment validates a temporal segment against current navigator state func (tn *TemporalNavigator) ValidateTemporalSegment(segment TemporalSegment) error { switch segment.Type { case TemporalLatest: // Always valid return nil case TemporalAny: // Always valid return nil case TemporalSpecific: if segment.Count < 0 || segment.Count > tn.maxVersion { return &TemporalConstraintError{ Operation: "validate_specific", RequestedStep: segment.Count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "specific version out of valid range", } } case TemporalRelative: if segment.Count < 0 { return fmt.Errorf("relative navigation count cannot be negative") } switch segment.Direction { case DirectionBackward: if !tn.CanNavigateBackward(segment.Count) { return &TemporalConstraintError{ Operation: "validate_backward", RequestedStep: segment.Count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "backward navigation would go before first version", } } case DirectionForward: if !tn.CanNavigateForward(segment.Count) { return &TemporalConstraintError{ Operation: "validate_forward", RequestedStep: segment.Count, CurrentVersion: tn.currentVersion, MaxVersion: tn.maxVersion, Message: "forward navigation would go beyond latest version", } } default: return fmt.Errorf("unknown temporal direction: %v", segment.Direction) } default: return fmt.Errorf("unknown temporal type: %v", segment.Type) } return nil }