Files
CHORUS/docs/comprehensive/packages/ucxl.md
anthonyrawlins f9c0395e03 docs: Add Phase 2 core package documentation (Execution, Config, Runtime, Security)
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>
2025-09-30 18:08:59 +10:00

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)