Comprehensive documentation for 7 critical packages covering execution engine, configuration management, runtime infrastructure, and security layers. Package Documentation Added: - pkg/execution - Complete task execution engine API (Docker sandboxing, image selection) - pkg/config - Configuration management (80+ env vars, dynamic assignments, SIGHUP reload) - internal/runtime - Shared P2P runtime (initialization, lifecycle, agent mode) - pkg/dht - Distributed hash table (LibP2P DHT, encrypted storage, bootstrap) - pkg/crypto - Cryptography (age encryption, key derivation, secure random) - pkg/ucxl - UCXL validation (decision publishing, content addressing, immutable audit) - pkg/shhh - Secrets management (sentinel, pattern matching, redaction, audit logging) Documentation Statistics (Phase 2): - 7 package files created (~12,000 lines total) - Complete API reference for all exported symbols - Line-by-line source code analysis - 30+ usage examples across packages - Implementation status tracking (Production/Beta/Alpha/TODO) - Cross-references to 20+ related documents Key Features Documented: - Docker Exec API usage (not SSH) for sandboxed execution - 4-tier language detection priority system - RuntimeConfig vs static Config with merge semantics - SIGHUP signal handling for dynamic reconfiguration - Graceful shutdown with dependency ordering - Age encryption integration (filippo.io/age) - DHT cache management and cleanup - UCXL address format (ucxl://) and decision schema - SHHH pattern matching and severity levels - Bootstrap peer priority (assignment > config > env) - Join stagger for thundering herd prevention Progress Tracking: - PROGRESS.md added with detailed completion status - Phase 1: 5 files complete (Foundation) - Phase 2: 7 files complete (Core Packages) - Total: 12 files, ~16,000 lines documented - Overall: 15% complete (12/62 planned files) Next Phase: Coordination & AI packages (pkg/slurp, pkg/election, pkg/ai, pkg/providers) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1154 lines
29 KiB
Markdown
1154 lines
29 KiB
Markdown
# UCXL Package Documentation
|
|
|
|
## Overview
|
|
|
|
The UCXL (Universal Collaboration eXchange Locator) package provides a comprehensive addressing scheme for CHORUS agents to reference, version, and navigate immutable decisions and content across the distributed system. UCXL addresses function similarly to URLs but are specifically designed for temporal navigation, role-based collaboration, and content-addressable storage within the CHORUS ecosystem.
|
|
|
|
## Table of Contents
|
|
|
|
- [UCXL Address Format](#ucxl-address-format)
|
|
- [Temporal Navigation](#temporal-navigation)
|
|
- [Decision Publishing](#decision-publishing)
|
|
- [Content Addressing](#content-addressing)
|
|
- [DHT Integration](#dht-integration)
|
|
- [Response Codes](#response-codes)
|
|
- [API Reference](#api-reference)
|
|
- [Usage Examples](#usage-examples)
|
|
|
|
## UCXL Address Format
|
|
|
|
### Address Structure
|
|
|
|
UCXL addresses follow a standardized URI format:
|
|
|
|
```
|
|
ucxl://agent:role@project:task/temporal_segment/path
|
|
```
|
|
|
|
### Components
|
|
|
|
| Component | Description | Validation | Examples |
|
|
|-----------|-------------|------------|----------|
|
|
| **agent** | Agent identifier or "any" for wildcard | Alphanumeric, hyphens, underscores | `agent1`, `chorus-bot`, `any` |
|
|
| **role** | Agent role in the project | Alphanumeric, hyphens, underscores | `developer`, `tester`, `admin`, `any` |
|
|
| **project** | Project identifier | Alphanumeric, hyphens, underscores | `project1`, `chorus`, `any` |
|
|
| **task** | Task identifier | Alphanumeric, hyphens, underscores | `task1`, `build`, `deploy`, `any` |
|
|
| **temporal_segment** | Version navigation | See [Temporal Navigation](#temporal-navigation) | `*^`, `*~5`, `~~3`, `^^2` |
|
|
| **path** | Optional resource path | Alphanumeric, slashes, dots, hyphens | `config.json`, `src/main.go` |
|
|
|
|
### Example Addresses
|
|
|
|
```go
|
|
// Latest version of a decision
|
|
"ucxl://agent1:developer@chorus:build/*^"
|
|
|
|
// Specific version 5 with file path
|
|
"ucxl://agent2:tester@project1:test/*~5/results.json"
|
|
|
|
// Navigate 3 versions backward
|
|
"ucxl://bot:admin@system:backup/~~3"
|
|
|
|
// Navigate 2 versions forward
|
|
"ucxl://ai:researcher@analysis:data/^^2/results"
|
|
|
|
// Wildcard matching - any agent in developer role
|
|
"ucxl://any:developer@chorus:any/*^"
|
|
```
|
|
|
|
## Temporal Navigation
|
|
|
|
### Temporal Segment Types
|
|
|
|
UCXL supports four types of temporal navigation:
|
|
|
|
#### 1. Latest Version (`*^`)
|
|
|
|
Navigates to the most recent version of the content.
|
|
|
|
```go
|
|
address := "ucxl://agent:role@project:task/*^"
|
|
// Always retrieves the latest decision
|
|
```
|
|
|
|
#### 2. Any Version (`*~`)
|
|
|
|
Matches any version of the content (useful for wildcard queries).
|
|
|
|
```go
|
|
address := "ucxl://agent:role@project:task/*~"
|
|
// Can retrieve any version that matches other criteria
|
|
```
|
|
|
|
#### 3. Specific Version (`*~N`)
|
|
|
|
References a specific version number (zero-indexed).
|
|
|
|
```go
|
|
address := "ucxl://agent:role@project:task/*~5"
|
|
// Retrieves exactly version 5
|
|
```
|
|
|
|
#### 4. Relative Navigation
|
|
|
|
Navigate relative to the current position:
|
|
|
|
**Backward (`~~N`)**: Move N versions backward
|
|
|
|
```go
|
|
address := "ucxl://agent:role@project:task/~~3"
|
|
// Navigate 3 versions backward from current
|
|
```
|
|
|
|
**Forward (`^^N`)**: Move N versions forward
|
|
|
|
```go
|
|
address := "ucxl://agent:role@project:task/^^2"
|
|
// Navigate 2 versions forward from current
|
|
```
|
|
|
|
### Temporal Navigator
|
|
|
|
The `TemporalNavigator` type manages version traversal with history tracking:
|
|
|
|
```go
|
|
// Create navigator with max version
|
|
navigator := ucxl.NewTemporalNavigator(10) // Versions 0-10
|
|
|
|
// Navigate to latest
|
|
result, err := navigator.Navigate(ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalLatest,
|
|
})
|
|
|
|
// Navigate backward 3 versions
|
|
result, err := navigator.Navigate(ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalRelative,
|
|
Direction: ucxl.DirectionBackward,
|
|
Count: 3,
|
|
})
|
|
|
|
// Check current position
|
|
current := navigator.GetCurrentVersion() // Returns: 7
|
|
|
|
// Validate before navigation
|
|
segment := ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalRelative,
|
|
Direction: ucxl.DirectionBackward,
|
|
Count: 20,
|
|
}
|
|
err := navigator.ValidateTemporalSegment(segment)
|
|
// Returns error: would go before version 0
|
|
```
|
|
|
|
### Navigation History
|
|
|
|
The navigator maintains a complete history of temporal traversals:
|
|
|
|
```go
|
|
// Get navigation history
|
|
history := navigator.GetHistory()
|
|
for _, step := range history {
|
|
fmt.Printf("From %d to %d via %s: success=%v\n",
|
|
step.FromVersion,
|
|
step.ToVersion,
|
|
step.Operation,
|
|
step.Success,
|
|
)
|
|
}
|
|
|
|
// Get last navigation
|
|
lastStep := navigator.GetLastNavigation()
|
|
if lastStep != nil {
|
|
fmt.Printf("Last navigation: %s\n", lastStep.Operation)
|
|
}
|
|
|
|
// Clear history
|
|
navigator.ClearHistory()
|
|
|
|
// Reset to latest version
|
|
navigator.Reset()
|
|
```
|
|
|
|
### Version Metadata
|
|
|
|
Associate metadata with specific versions:
|
|
|
|
```go
|
|
// Set version information
|
|
navigator.SetVersionInfo(5, ucxl.VersionInfo{
|
|
Version: 5,
|
|
Created: time.Now(),
|
|
Author: "agent-007",
|
|
Description: "Fixed critical bug in authentication",
|
|
Tags: []string{"bugfix", "security"},
|
|
})
|
|
|
|
// Retrieve version info
|
|
info, exists := navigator.GetVersionInfo(5)
|
|
if exists {
|
|
fmt.Printf("Version %d by %s: %s\n",
|
|
info.Version,
|
|
info.Author,
|
|
info.Description,
|
|
)
|
|
}
|
|
|
|
// Get all version metadata
|
|
allVersions := navigator.GetAllVersions()
|
|
```
|
|
|
|
## Decision Publishing
|
|
|
|
### DecisionPublisher
|
|
|
|
The `DecisionPublisher` handles publishing immutable task completion decisions to encrypted DHT storage. Decisions are content-addressed using SHA-256 hashing and stored with role-based encryption.
|
|
|
|
```go
|
|
// Create decision publisher
|
|
publisher := ucxl.NewDecisionPublisher(
|
|
ctx,
|
|
config,
|
|
dhtStorage,
|
|
"node-001",
|
|
"chorus-agent",
|
|
)
|
|
```
|
|
|
|
### TaskDecision Schema
|
|
|
|
```go
|
|
type TaskDecision struct {
|
|
Agent string `json:"agent"`
|
|
Role string `json:"role"`
|
|
Project string `json:"project"`
|
|
Task string `json:"task"`
|
|
Decision string `json:"decision"`
|
|
Context map[string]interface{} `json:"context"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Success bool `json:"success"`
|
|
ErrorMessage string `json:"error_message,omitempty"`
|
|
FilesModified []string `json:"files_modified,omitempty"`
|
|
LinesChanged int `json:"lines_changed,omitempty"`
|
|
TestResults *TestResults `json:"test_results,omitempty"`
|
|
Dependencies []string `json:"dependencies,omitempty"`
|
|
NextSteps []string `json:"next_steps,omitempty"`
|
|
}
|
|
|
|
type TestResults struct {
|
|
Passed int `json:"passed"`
|
|
Failed int `json:"failed"`
|
|
Skipped int `json:"skipped"`
|
|
Coverage float64 `json:"coverage,omitempty"`
|
|
FailedTests []string `json:"failed_tests,omitempty"`
|
|
}
|
|
```
|
|
|
|
### Publishing Decisions
|
|
|
|
#### Basic Task Completion
|
|
|
|
```go
|
|
err := publisher.PublishTaskCompletion(
|
|
"build-project",
|
|
true,
|
|
"Successfully built project with no errors",
|
|
[]string{"src/main.go", "pkg/api/handler.go"},
|
|
)
|
|
```
|
|
|
|
#### Code Decision with Test Results
|
|
|
|
```go
|
|
testResults := &ucxl.TestResults{
|
|
Passed: 42,
|
|
Failed: 0,
|
|
Skipped: 3,
|
|
Coverage: 87.5,
|
|
}
|
|
|
|
err := publisher.PublishCodeDecision(
|
|
"implement-auth",
|
|
"Implemented JWT authentication with refresh tokens",
|
|
[]string{
|
|
"pkg/auth/jwt.go",
|
|
"pkg/auth/middleware.go",
|
|
"pkg/auth/jwt_test.go",
|
|
},
|
|
345, // lines changed
|
|
testResults,
|
|
[]string{"github.com/golang-jwt/jwt/v5"},
|
|
)
|
|
```
|
|
|
|
#### Architectural Decision
|
|
|
|
```go
|
|
err := publisher.PublishArchitecturalDecision(
|
|
"choose-database",
|
|
"Selected PostgreSQL for primary database",
|
|
"PostgreSQL provides ACID compliance, JSON support, and excellent Go libraries",
|
|
[]string{
|
|
"MongoDB - considered but lacking strong consistency",
|
|
"MySQL - considered but PostgreSQL has better JSON support",
|
|
},
|
|
[]string{
|
|
"Must implement connection pooling",
|
|
"Consider read replicas for scaling",
|
|
"Plan migration strategy from current SQLite",
|
|
},
|
|
[]string{
|
|
"Set up PostgreSQL cluster",
|
|
"Implement database migrations",
|
|
"Update connection configuration",
|
|
},
|
|
)
|
|
```
|
|
|
|
#### Custom Decision
|
|
|
|
```go
|
|
decision := &ucxl.TaskDecision{
|
|
Task: "security-audit",
|
|
Decision: "Completed security audit - no critical findings",
|
|
Success: true,
|
|
Context: map[string]interface{}{
|
|
"decision_type": "security",
|
|
"audit_scope": "authentication",
|
|
"tools_used": []string{"gosec", "trivy"},
|
|
"findings_count": 12,
|
|
"critical_count": 0,
|
|
"high_count": 2,
|
|
"medium_count": 5,
|
|
"low_count": 5,
|
|
},
|
|
}
|
|
|
|
err := publisher.PublishTaskDecision(decision)
|
|
```
|
|
|
|
### Querying Decisions
|
|
|
|
#### Search Recent Decisions
|
|
|
|
```go
|
|
// Query decisions from last 24 hours
|
|
decisions, err := publisher.QueryRecentDecisions(
|
|
"agent-007", // agent filter
|
|
"developer", // role filter
|
|
"chorus", // project filter
|
|
10, // limit
|
|
time.Now().Add(-24*time.Hour), // since
|
|
)
|
|
|
|
for _, metadata := range decisions {
|
|
fmt.Printf("Decision: %s (created: %s)\n",
|
|
metadata.Address,
|
|
metadata.CreatedAt,
|
|
)
|
|
}
|
|
```
|
|
|
|
#### Retrieve Decision Content
|
|
|
|
```go
|
|
// Get specific decision
|
|
decision, err := publisher.GetDecisionContent(
|
|
"ucxl://agent-007:developer@chorus:build/*^",
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("Task: %s\n", decision.Task)
|
|
fmt.Printf("Success: %v\n", decision.Success)
|
|
fmt.Printf("Decision: %s\n", decision.Decision)
|
|
if decision.TestResults != nil {
|
|
fmt.Printf("Tests: %d passed, %d failed\n",
|
|
decision.TestResults.Passed,
|
|
decision.TestResults.Failed,
|
|
)
|
|
}
|
|
```
|
|
|
|
### Decision Subscriptions
|
|
|
|
Subscribe to new decisions in real-time (polling-based, pubsub coming soon):
|
|
|
|
```go
|
|
err := publisher.SubscribeToDecisions(
|
|
"developer", // role filter
|
|
func(decision *ucxl.TaskDecision, metadata *storage.UCXLMetadata) {
|
|
fmt.Printf("New decision from %s: %s\n",
|
|
decision.Agent,
|
|
decision.Decision,
|
|
)
|
|
|
|
// Process decision
|
|
if decision.Success && decision.TestResults != nil {
|
|
if decision.TestResults.Failed > 0 {
|
|
fmt.Printf("Warning: %d tests failed\n",
|
|
decision.TestResults.Failed,
|
|
)
|
|
}
|
|
}
|
|
},
|
|
)
|
|
```
|
|
|
|
## Content Addressing
|
|
|
|
### SHA-256 Hashing
|
|
|
|
UCXL uses SHA-256 content addressing to ensure decision immutability:
|
|
|
|
1. **Decision Serialization**: TaskDecision is serialized to JSON
|
|
2. **Hash Generation**: SHA-256 hash computed from JSON bytes
|
|
3. **Storage Key**: Hash used as DHT storage key
|
|
4. **Verification**: Content can be verified by recomputing hash
|
|
|
|
```go
|
|
// Internal process (handled automatically)
|
|
decisionContent, _ := json.MarshalIndent(decision, "", " ")
|
|
hash := sha256.Sum256(decisionContent)
|
|
storageKey := hex.EncodeToString(hash[:])
|
|
```
|
|
|
|
### Content Retrieval
|
|
|
|
Content is retrieved using UCXL addresses, which are resolved to content hashes:
|
|
|
|
```go
|
|
// 1. Parse UCXL address
|
|
address, err := ucxl.Parse("ucxl://agent:role@project:task/*^")
|
|
|
|
// 2. Resolve address to content hash
|
|
contentHash, err := dhtStorage.ResolveUCXLAddress(address.String())
|
|
|
|
// 3. Retrieve content by hash
|
|
content, metadata, err := dhtStorage.RetrieveByHash(contentHash)
|
|
|
|
// 4. Verify content integrity
|
|
computedHash := sha256.Sum256(content)
|
|
if hex.EncodeToString(computedHash[:]) != contentHash {
|
|
return errors.New("content integrity check failed")
|
|
}
|
|
```
|
|
|
|
## DHT Integration
|
|
|
|
### Storage Operations
|
|
|
|
The UCXL package integrates with CHORUS's encrypted DHT storage layer:
|
|
|
|
#### Store Content
|
|
|
|
```go
|
|
err := dhtStorage.StoreUCXLContent(
|
|
ucxlAddress, // UCXL address
|
|
decisionContent, // Content bytes
|
|
role, // Creator role (for encryption)
|
|
"decision", // Content type
|
|
)
|
|
```
|
|
|
|
#### Announce Content
|
|
|
|
After storing, announce content availability to the DHT network:
|
|
|
|
```go
|
|
err := dhtStorage.AnnounceContent(ucxlAddress)
|
|
// Broadcasts content availability to DHT peers
|
|
```
|
|
|
|
#### Retrieve Content
|
|
|
|
```go
|
|
content, metadata, err := dhtStorage.RetrieveUCXLContent(ucxlAddress)
|
|
|
|
fmt.Printf("Content type: %s\n", metadata.ContentType)
|
|
fmt.Printf("Creator role: %s\n", metadata.CreatorRole)
|
|
fmt.Printf("Created at: %s\n", metadata.CreatedAt)
|
|
fmt.Printf("Size: %d bytes\n", metadata.Size)
|
|
```
|
|
|
|
#### Search Content
|
|
|
|
```go
|
|
query := &storage.SearchQuery{
|
|
Agent: "agent-007",
|
|
Role: "developer",
|
|
Project: "chorus",
|
|
ContentType: "decision",
|
|
CreatedAfter: time.Now().Add(-7 * 24 * time.Hour),
|
|
Limit: 50,
|
|
}
|
|
|
|
results, err := dhtStorage.SearchContent(query)
|
|
for _, metadata := range results {
|
|
fmt.Printf("Found: %s\n", metadata.Address)
|
|
}
|
|
```
|
|
|
|
### Role-Based Encryption
|
|
|
|
Content is encrypted based on the creator's role:
|
|
|
|
```go
|
|
// When storing
|
|
err := dhtStorage.StoreUCXLContent(
|
|
address,
|
|
content,
|
|
"developer", // Creator role - determines encryption key
|
|
contentType,
|
|
)
|
|
|
|
// When retrieving
|
|
// Automatic decryption if requester has access to role's key
|
|
content, metadata, err := dhtStorage.RetrieveUCXLContent(address)
|
|
```
|
|
|
|
### DHT Metrics
|
|
|
|
Monitor DHT storage performance:
|
|
|
|
```go
|
|
metrics := dhtStorage.GetMetrics()
|
|
|
|
fmt.Printf("Total stored: %d\n", metrics["total_stored"])
|
|
fmt.Printf("Total retrieved: %d\n", metrics["total_retrieved"])
|
|
fmt.Printf("Cache hits: %d\n", metrics["cache_hits"])
|
|
fmt.Printf("Cache misses: %d\n", metrics["cache_misses"])
|
|
```
|
|
|
|
## Response Codes
|
|
|
|
UCXL defines standardized response codes for operations:
|
|
|
|
### Success Codes (2xx)
|
|
|
|
| Code | Description | HTTP Status |
|
|
|------|-------------|-------------|
|
|
| `UCXL-200-SUCCESS` | Request completed successfully | 200 |
|
|
| `UCXL-201-CREATED` | Resource created successfully | 201 |
|
|
| `UCXL-202-ACCEPTED` | Request accepted for processing | 202 |
|
|
| `UCXL-204-NO_CONTENT` | Request completed with no content | 204 |
|
|
|
|
### Client Error Codes (4xx)
|
|
|
|
| Code | Description | HTTP Status |
|
|
|------|-------------|-------------|
|
|
| `UCXL-400-BAD_REQUEST` | Invalid request format | 400 |
|
|
| `UCXL-400-INVALID_ADDRESS` | UCXL address validation failed | 400 |
|
|
| `UCXL-400-INVALID_PAYLOAD` | Request payload validation failed | 400 |
|
|
| `UCXL-400-TEMPORAL_INVALID` | Invalid temporal navigation | 400 |
|
|
| `UCXL-400-INVALID_ROLE` | Invalid or unknown role | 400 |
|
|
| `UCXL-401-UNAUTHORIZED` | Authentication required | 401 |
|
|
| `UCXL-403-FORBIDDEN` | Insufficient permissions | 403 |
|
|
| `UCXL-404-NOT_FOUND` | Resource not found | 404 |
|
|
| `UCXL-404-RESOLUTION_FAILED` | Address resolution failed | 404 |
|
|
| `UCXL-404-EXPERTISE_NOT_AVAILABLE` | Requested expertise not available | 404 |
|
|
| `UCXL-404-PROJECT_NOT_FOUND` | Project not found | 404 |
|
|
| `UCXL-408-COLLABORATION_TIMEOUT` | Collaboration request timeout | 408 |
|
|
| `UCXL-422-UNPROCESSABLE` | Request cannot be processed | 422 |
|
|
| `UCXL-422-NAVIGATION_FAILED` | Temporal navigation failed | 422 |
|
|
|
|
### Server Error Codes (5xx)
|
|
|
|
| Code | Description | HTTP Status |
|
|
|------|-------------|-------------|
|
|
| `UCXL-500-INTERNAL_ERROR` | Internal server error | 500 |
|
|
| `UCXL-500-STORAGE_FAILED` | DHT storage operation failed | 500 |
|
|
| `UCXL-500-ANNOUNCE_FAILED` | Content announcement failed | 500 |
|
|
| `UCXL-500-COLLABORATION_FAILED` | Collaboration operation failed | 500 |
|
|
| `UCXL-501-NOT_IMPLEMENTED` | Feature not implemented | 501 |
|
|
| `UCXL-503-SERVICE_UNAVAILABLE` | Service temporarily unavailable | 503 |
|
|
|
|
### Using Response Codes
|
|
|
|
```go
|
|
// Create response builder
|
|
rb := ucxl.NewResponseBuilder("req-12345", "ucxi-server")
|
|
|
|
// Success response
|
|
response := rb.OK(map[string]interface{}{
|
|
"address": address.String(),
|
|
"version": 5,
|
|
})
|
|
|
|
// Error response
|
|
error := rb.InvalidAddress(
|
|
"Agent component cannot be empty",
|
|
"/address/agent",
|
|
map[string]interface{}{
|
|
"provided": address.Agent,
|
|
"required": "non-empty string",
|
|
},
|
|
)
|
|
|
|
// Get HTTP status for UCXL code
|
|
httpStatus := ucxl.GetHTTPStatus(ucxl.CodeInvalidAddress)
|
|
// Returns: 400
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### Address Parsing
|
|
|
|
```go
|
|
// Parse address string
|
|
address, err := ucxl.Parse("ucxl://agent:role@project:task/*^")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Access components
|
|
fmt.Println(address.Agent) // "agent"
|
|
fmt.Println(address.Role) // "role"
|
|
fmt.Println(address.Project) // "project"
|
|
fmt.Println(address.Task) // "task"
|
|
fmt.Println(address.TemporalSegment.Type) // TemporalLatest
|
|
|
|
// Convert back to string
|
|
canonical := address.String()
|
|
```
|
|
|
|
### Address Validation
|
|
|
|
```go
|
|
// Validate address
|
|
err := address.Validate()
|
|
if err != nil {
|
|
if valErr, ok := err.(*ucxl.ValidationError); ok {
|
|
fmt.Printf("Validation failed in %s: %s\n",
|
|
valErr.Field,
|
|
valErr.Message,
|
|
)
|
|
}
|
|
}
|
|
|
|
// Quick validation check
|
|
if address.IsValid() {
|
|
fmt.Println("Address is valid")
|
|
}
|
|
```
|
|
|
|
### Address Matching
|
|
|
|
```go
|
|
// Create pattern with wildcards
|
|
pattern, _ := ucxl.Parse("ucxl://any:developer@chorus:any/*^")
|
|
|
|
// Test if address matches pattern
|
|
address, _ := ucxl.Parse("ucxl://agent-007:developer@chorus:build/*^")
|
|
if address.Matches(pattern) {
|
|
fmt.Println("Address matches pattern")
|
|
}
|
|
|
|
// Check if address uses wildcards
|
|
if address.IsWildcard() {
|
|
fmt.Println("Address contains wildcards")
|
|
}
|
|
```
|
|
|
|
### Address Manipulation
|
|
|
|
```go
|
|
// Clone address
|
|
addressCopy := address.Clone()
|
|
|
|
// Modify clone without affecting original
|
|
addressCopy.Task = "deploy"
|
|
addressCopy.TemporalSegment = ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalSpecific,
|
|
Count: 10,
|
|
}
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Example 1: Publishing and Retrieving Code Decisions
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"chorus/pkg/ucxl"
|
|
"chorus/pkg/config"
|
|
"chorus/pkg/storage"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
cfg := config.LoadConfig()
|
|
dhtStorage := storage.NewDHTStorage(cfg)
|
|
|
|
// Create publisher
|
|
publisher := ucxl.NewDecisionPublisher(
|
|
ctx,
|
|
cfg,
|
|
dhtStorage,
|
|
"node-001",
|
|
"agent-007",
|
|
)
|
|
|
|
// Publish code decision
|
|
testResults := &ucxl.TestResults{
|
|
Passed: 128,
|
|
Failed: 2,
|
|
Skipped: 5,
|
|
Coverage: 84.2,
|
|
FailedTests: []string{
|
|
"TestAuthTokenExpiry",
|
|
"TestRateLimitExceeded",
|
|
},
|
|
}
|
|
|
|
err := publisher.PublishCodeDecision(
|
|
"implement-api-v2",
|
|
"Implemented v2 API with improved error handling and rate limiting",
|
|
[]string{
|
|
"pkg/api/v2/handler.go",
|
|
"pkg/api/v2/middleware.go",
|
|
"pkg/api/v2/errors.go",
|
|
},
|
|
892,
|
|
testResults,
|
|
[]string{
|
|
"github.com/gin-gonic/gin",
|
|
"github.com/go-redis/redis/v8",
|
|
},
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Println("Decision published successfully")
|
|
|
|
// Retrieve decision
|
|
decision, err := publisher.GetDecisionContent(
|
|
"ucxl://agent-007:developer@chorus:implement-api-v2/*^",
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("\nRetrieved Decision:\n")
|
|
fmt.Printf("Task: %s\n", decision.Task)
|
|
fmt.Printf("Success: %v\n", decision.Success)
|
|
fmt.Printf("Files Modified: %d\n", len(decision.FilesModified))
|
|
fmt.Printf("Lines Changed: %d\n", decision.LinesChanged)
|
|
|
|
if decision.TestResults != nil {
|
|
fmt.Printf("\nTest Results:\n")
|
|
fmt.Printf(" Passed: %d\n", decision.TestResults.Passed)
|
|
fmt.Printf(" Failed: %d\n", decision.TestResults.Failed)
|
|
fmt.Printf(" Coverage: %.1f%%\n", decision.TestResults.Coverage)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 2: Temporal Navigation
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"chorus/pkg/ucxl"
|
|
)
|
|
|
|
func main() {
|
|
// Create navigator with 20 versions (0-20)
|
|
navigator := ucxl.NewTemporalNavigator(20)
|
|
|
|
// Add version metadata
|
|
for i := 0; i <= 20; i++ {
|
|
navigator.SetVersionInfo(i, ucxl.VersionInfo{
|
|
Version: i,
|
|
Created: time.Now().Add(-time.Duration(20-i) * time.Hour),
|
|
Author: fmt.Sprintf("agent-%03d", (i%5)+1),
|
|
Description: fmt.Sprintf("Version %d update", i),
|
|
Tags: []string{"build", "tested"},
|
|
})
|
|
}
|
|
|
|
fmt.Printf("Starting at version: %d\n", navigator.GetCurrentVersion())
|
|
|
|
// Navigate to specific version
|
|
result, err := navigator.Navigate(ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalSpecific,
|
|
Count: 15,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("Navigated to version: %d\n", result.TargetVersion)
|
|
if result.VersionInfo != nil {
|
|
fmt.Printf(" Author: %s\n", result.VersionInfo.Author)
|
|
fmt.Printf(" Created: %s\n", result.VersionInfo.Created)
|
|
}
|
|
|
|
// Navigate backward 5 versions
|
|
result, err = navigator.Navigate(ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalRelative,
|
|
Direction: ucxl.DirectionBackward,
|
|
Count: 5,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("After backward navigation: %d\n", result.TargetVersion)
|
|
|
|
// Navigate to latest
|
|
result, err = navigator.Navigate(ucxl.TemporalSegment{
|
|
Type: ucxl.TemporalLatest,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("Latest version: %d\n", result.TargetVersion)
|
|
|
|
// Display navigation history
|
|
fmt.Println("\nNavigation History:")
|
|
for i, step := range navigator.GetHistory() {
|
|
status := "✓"
|
|
if !step.Success {
|
|
status = "✗"
|
|
}
|
|
fmt.Printf("%d. %s %s: %d → %d\n",
|
|
i+1,
|
|
status,
|
|
step.Operation,
|
|
step.FromVersion,
|
|
step.ToVersion,
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 3: Address Wildcards and Search
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"chorus/pkg/ucxl"
|
|
"chorus/pkg/config"
|
|
"chorus/pkg/storage"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
cfg := config.LoadConfig()
|
|
dhtStorage := storage.NewDHTStorage(cfg)
|
|
|
|
publisher := ucxl.NewDecisionPublisher(
|
|
ctx,
|
|
cfg,
|
|
dhtStorage,
|
|
"node-001",
|
|
"search-agent",
|
|
)
|
|
|
|
// Query all developer decisions from last week
|
|
oneWeekAgo := time.Now().Add(-7 * 24 * time.Hour)
|
|
|
|
decisions, err := publisher.QueryRecentDecisions(
|
|
"", // any agent
|
|
"developer", // developer role only
|
|
"chorus", // chorus project
|
|
100, // limit
|
|
oneWeekAgo,
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("Found %d decisions\n\n", len(decisions))
|
|
|
|
// Group by task
|
|
taskCounts := make(map[string]int)
|
|
successCounts := make(map[string]int)
|
|
|
|
for _, metadata := range decisions {
|
|
// Parse address
|
|
addr, err := ucxl.Parse(metadata.Address)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
taskCounts[addr.Task]++
|
|
|
|
// Get decision details
|
|
decision, err := publisher.GetDecisionContent(metadata.Address)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
if decision.Success {
|
|
successCounts[addr.Task]++
|
|
}
|
|
}
|
|
|
|
// Display statistics
|
|
fmt.Println("Task Statistics:")
|
|
for task, total := range taskCounts {
|
|
success := successCounts[task]
|
|
successRate := float64(success) / float64(total) * 100
|
|
fmt.Printf(" %s: %d total, %d successful (%.1f%%)\n",
|
|
task,
|
|
total,
|
|
success,
|
|
successRate,
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 4: Decision Subscription
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"chorus/pkg/ucxl"
|
|
"chorus/pkg/config"
|
|
"chorus/pkg/storage"
|
|
)
|
|
|
|
func main() {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
cfg := config.LoadConfig()
|
|
dhtStorage := storage.NewDHTStorage(cfg)
|
|
|
|
publisher := ucxl.NewDecisionPublisher(
|
|
ctx,
|
|
cfg,
|
|
dhtStorage,
|
|
"node-001",
|
|
"watcher-agent",
|
|
)
|
|
|
|
// Subscribe to all tester decisions
|
|
err := publisher.SubscribeToDecisions(
|
|
"tester",
|
|
func(decision *ucxl.TaskDecision, metadata *storage.UCXLMetadata) {
|
|
fmt.Printf("\n[NEW DECISION] %s\n", metadata.CreatedAt)
|
|
fmt.Printf("Agent: %s\n", decision.Agent)
|
|
fmt.Printf("Task: %s\n", decision.Task)
|
|
fmt.Printf("Success: %v\n", decision.Success)
|
|
|
|
if decision.TestResults != nil {
|
|
total := decision.TestResults.Passed +
|
|
decision.TestResults.Failed +
|
|
decision.TestResults.Skipped
|
|
fmt.Printf("Tests: %d/%d passed\n",
|
|
decision.TestResults.Passed,
|
|
total,
|
|
)
|
|
|
|
if decision.TestResults.Failed > 0 {
|
|
fmt.Printf("⚠ Failed tests:\n")
|
|
for _, test := range decision.TestResults.FailedTests {
|
|
fmt.Printf(" - %s\n", test)
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println("---")
|
|
},
|
|
)
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Println("Subscribed to tester decisions. Press Ctrl+C to exit.")
|
|
|
|
// Wait for interrupt
|
|
sigChan := make(chan os.Signal, 1)
|
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
|
<-sigChan
|
|
|
|
fmt.Println("\nShutting down...")
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Address Design
|
|
|
|
1. **Use meaningful identifiers**: Choose descriptive agent, role, project, and task names
|
|
2. **Prefer specific over wildcards**: Use wildcards only when necessary for queries
|
|
3. **Version consistently**: Use semantic versioning strategies for temporal segments
|
|
4. **Document paths**: Use clear file paths in the path component
|
|
|
|
### Decision Publishing
|
|
|
|
1. **Publish atomically**: Complete all task work before publishing decision
|
|
2. **Include context**: Provide rich context in the Context field
|
|
3. **Track dependencies**: Always list external dependencies
|
|
4. **Test before publishing**: Ensure test results are accurate
|
|
5. **Plan next steps**: Include actionable next steps for continuity
|
|
|
|
### Temporal Navigation
|
|
|
|
1. **Validate before navigation**: Use `ValidateTemporalSegment()` to check feasibility
|
|
2. **Handle errors gracefully**: Navigation can fail at boundaries
|
|
3. **Track history**: Maintain navigation history for debugging
|
|
4. **Use version metadata**: Annotate versions with useful information
|
|
|
|
### DHT Integration
|
|
|
|
1. **Announce after storing**: Always announce content availability
|
|
2. **Handle network failures**: DHT operations can fail; implement retries
|
|
3. **Monitor metrics**: Track DHT performance and storage usage
|
|
4. **Encrypt sensitive data**: Use role-based encryption for sensitive decisions
|
|
|
|
## Error Handling
|
|
|
|
Common error patterns and how to handle them:
|
|
|
|
```go
|
|
// Address parsing errors
|
|
address, err := ucxl.Parse(rawAddress)
|
|
if err != nil {
|
|
if valErr, ok := err.(*ucxl.ValidationError); ok {
|
|
log.Printf("Invalid %s: %s", valErr.Field, valErr.Message)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// Temporal navigation errors
|
|
result, err := navigator.Navigate(segment)
|
|
if err != nil {
|
|
if tcErr, ok := err.(*ucxl.TemporalConstraintError); ok {
|
|
log.Printf("Navigation failed: %s (current: %d, max: %d)",
|
|
tcErr.Message,
|
|
tcErr.CurrentVersion,
|
|
tcErr.MaxVersion,
|
|
)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// DHT storage errors
|
|
content, metadata, err := dhtStorage.RetrieveUCXLContent(address)
|
|
if err != nil {
|
|
if errors.Is(err, storage.ErrNotFound) {
|
|
log.Println("Decision not found")
|
|
} else if errors.Is(err, storage.ErrDecryptionFailed) {
|
|
log.Println("Insufficient permissions to decrypt content")
|
|
} else {
|
|
log.Printf("DHT retrieval failed: %v", err)
|
|
}
|
|
return err
|
|
}
|
|
```
|
|
|
|
## Integration Points
|
|
|
|
### CHORUS Agent Integration
|
|
|
|
```go
|
|
// In agent initialization
|
|
publisher := ucxl.NewDecisionPublisher(
|
|
ctx,
|
|
config,
|
|
dhtStorage,
|
|
nodeID,
|
|
agentName,
|
|
)
|
|
agent.publisher = publisher
|
|
|
|
// In task execution
|
|
func (a *Agent) executeTask(task Task) error {
|
|
// Execute task logic
|
|
result := task.Execute()
|
|
|
|
// Publish decision
|
|
err := a.publisher.PublishTaskDecision(&ucxl.TaskDecision{
|
|
Task: task.Name(),
|
|
Decision: result.Summary(),
|
|
Success: result.Success(),
|
|
Context: result.Context(),
|
|
})
|
|
|
|
return err
|
|
}
|
|
```
|
|
|
|
### UCXI Server Integration
|
|
|
|
```go
|
|
// In UCXI server handlers
|
|
func (s *Server) handleResolve(w http.ResponseWriter, r *http.Request) {
|
|
rawAddress := r.URL.Query().Get("address")
|
|
|
|
address, err := ucxl.Parse(rawAddress)
|
|
if err != nil {
|
|
rb := ucxl.NewResponseBuilder(requestID, "ucxi-server")
|
|
writeError(w, rb.InvalidAddress(
|
|
"Failed to parse UCXL address",
|
|
"/address",
|
|
err.Error(),
|
|
))
|
|
return
|
|
}
|
|
|
|
// Resolve and return
|
|
content, metadata, err := s.dhtStorage.RetrieveUCXLContent(address.String())
|
|
if err != nil {
|
|
rb := ucxl.NewResponseBuilder(requestID, "ucxi-server")
|
|
writeError(w, rb.NotFound(
|
|
"Decision not found",
|
|
address.String(),
|
|
))
|
|
return
|
|
}
|
|
|
|
rb := ucxl.NewResponseBuilder(requestID, "ucxi-server")
|
|
writeSuccess(w, rb.OK(map[string]interface{}{
|
|
"address": address.String(),
|
|
"content": string(content),
|
|
"metadata": metadata,
|
|
}))
|
|
}
|
|
```
|
|
|
|
## See Also
|
|
|
|
- [CHORUS Architecture](../architecture/overview.md)
|
|
- [DHT Storage](../storage/dht.md)
|
|
- [Agent Collaboration](../collaboration/agents.md)
|
|
- [SHHH Security Package](shhh.md) |