Files
bzzz/pkg/ucxl/temporal.go
anthonyrawlins b207f32d9e Implement UCXL Protocol Foundation (Phase 1)
- Add complete UCXL address parser with BNF grammar validation
- Implement temporal navigation system with bounds checking
- Create UCXI HTTP server with REST-like operations
- Add comprehensive test suite with 87 passing tests
- Integrate with existing BZZZ architecture (opt-in via config)
- Support semantic addressing with wildcards and version control

Core Features:
- UCXL address format: ucxl://agent:role@project:task/temporal/path
- Temporal segments: *^, ~~N, ^^N, *~, *~N with navigation logic
- UCXI endpoints: GET/PUT/POST/DELETE/ANNOUNCE operations
- Production-ready with error handling and graceful shutdown

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 07:38:04 +10:00

377 lines
10 KiB
Go

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
}