# BZZZ v2 Implementation Roadmap: UCXL Integration ## Phase 1: Foundation Implementation (Weeks 1-2) ### Week 1: UCXL Address Parser Implementation #### 1.1 Replace existing `pkg/protocol/uri.go` with UCXL support **File:** `/pkg/protocol/ucxl_address.go` ```go package protocol import ( "fmt" "net/url" "regexp" "strings" "time" ) // UCXLAddress represents a parsed UCXL address with temporal navigation // Grammar: ucxl://agent:role@project:task/temporal_segment/path[?query][#fragment] type UCXLAddress struct { // Core semantic addressing Agent string `json:"agent"` // "gpt4", "claude", "any" Role string `json:"role"` // "architect", "reviewer", "any" Project string `json:"project"` // "bzzz", "chorus", "any" Task string `json:"task"` // "v2-migration", "auth", "any" // Temporal navigation TemporalSegment string `json:"temporal_segment"` // "~~", "^^", "*^", "*~", ISO8601 // Resource path Path string `json:"path"` // "/decisions/architecture.json" // Standard URI components Query string `json:"query,omitempty"` Fragment string `json:"fragment,omitempty"` Raw string `json:"raw"` // Resolved temporal information ResolvedTime *time.Time `json:"resolved_time,omitempty"` } // Temporal navigation constants const ( UCXLScheme = "ucxl" TemporalBackward = "~~" // Navigate backward in time TemporalForward = "^^" // Navigate forward in time TemporalLatest = "*^" // Latest entry TemporalFirst = "*~" // First entry AnyWildcard = "any" // Wildcard for any component ) // Validation patterns for UCXL components var ( agentPattern = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$|^any$`) rolePattern = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$|^any$`) projectPattern = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$|^any$`) taskPattern = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$|^any$`) temporalPattern = regexp.MustCompile(`^(~~|\^\^|\*\^|\*~|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*Z?)$`) pathPattern = regexp.MustCompile(`^(/[a-zA-Z0-9\-_/.]*)?$`) ) // ParseUCXLAddress parses a UCXL URI string func ParseUCXLAddress(uri string) (*UCXLAddress, error) { if uri == "" { return nil, fmt.Errorf("empty UCXL address") } if !strings.HasPrefix(uri, UCXLScheme+"://") { return nil, fmt.Errorf("invalid scheme: expected '%s'", UCXLScheme) } // Parse using standard URL parser parsedURL, err := url.Parse(uri) if err != nil { return nil, fmt.Errorf("failed to parse UCXL address: %w", err) } // Extract agent:role from user info userInfo := parsedURL.User if userInfo == nil { return nil, fmt.Errorf("missing agent:role information") } agent := userInfo.Username() role, hasRole := userInfo.Password() if !hasRole { return nil, fmt.Errorf("missing role information") } // Extract project:task from host hostParts := strings.Split(parsedURL.Host, ":") if len(hostParts) != 2 { return nil, fmt.Errorf("invalid project:task format") } project := hostParts[0] task := hostParts[1] // Parse temporal segment and path pathParts := strings.SplitN(strings.TrimPrefix(parsedURL.Path, "/"), "/", 2) temporalSegment := "" resourcePath := "" if len(pathParts) > 0 && pathParts[0] != "" { temporalSegment = pathParts[0] } if len(pathParts) > 1 { resourcePath = "/" + pathParts[1] } address := &UCXLAddress{ Agent: agent, Role: role, Project: project, Task: task, TemporalSegment: temporalSegment, Path: resourcePath, Query: parsedURL.RawQuery, Fragment: parsedURL.Fragment, Raw: uri, } if err := address.Validate(); err != nil { return nil, fmt.Errorf("validation failed: %w", err) } return address, nil } // Validate validates UCXL address components func (addr *UCXLAddress) Validate() error { if !agentPattern.MatchString(addr.Agent) { return fmt.Errorf("invalid agent: %s", addr.Agent) } if !rolePattern.MatchString(addr.Role) { return fmt.Errorf("invalid role: %s", addr.Role) } if !projectPattern.MatchString(addr.Project) { return fmt.Errorf("invalid project: %s", addr.Project) } if !taskPattern.MatchString(addr.Task) { return fmt.Errorf("invalid task: %s", addr.Task) } if addr.TemporalSegment != "" && !temporalPattern.MatchString(addr.TemporalSegment) { return fmt.Errorf("invalid temporal segment: %s", addr.TemporalSegment) } if !pathPattern.MatchString(addr.Path) { return fmt.Errorf("invalid path: %s", addr.Path) } return nil } // ResolveTemporalSegment resolves temporal navigation tokens to actual timestamps func (addr *UCXLAddress) ResolveTemporalSegment(navigator TemporalNavigator) error { if addr.TemporalSegment == "" { return nil } switch addr.TemporalSegment { case TemporalLatest: timestamp, err := navigator.GetLatestTimestamp(addr) if err != nil { return err } addr.ResolvedTime = ×tamp case TemporalFirst: timestamp, err := navigator.GetFirstTimestamp(addr) if err != nil { return err } addr.ResolvedTime = ×tamp case TemporalBackward, TemporalForward: // These require context of current position return fmt.Errorf("relative navigation requires current context") default: // Parse as ISO8601 timestamp timestamp, err := time.Parse(time.RFC3339, addr.TemporalSegment) if err != nil { return fmt.Errorf("invalid timestamp format: %w", err) } addr.ResolvedTime = ×tamp } return nil } // Matches checks if this address matches another (with wildcard support) func (addr *UCXLAddress) Matches(other *UCXLAddress) bool { return componentMatches(addr.Agent, other.Agent) && componentMatches(addr.Role, other.Role) && componentMatches(addr.Project, other.Project) && componentMatches(addr.Task, other.Task) && pathMatches(addr.Path, other.Path) } func componentMatches(a, b string) bool { return a == b || a == AnyWildcard || b == AnyWildcard } func pathMatches(a, b string) bool { if a == "" || b == "" { return true } return a == b } // String returns canonical string representation func (addr *UCXLAddress) String() string { uri := fmt.Sprintf("%s://%s:%s@%s:%s", UCXLScheme, addr.Agent, addr.Role, addr.Project, addr.Task) if addr.TemporalSegment != "" { uri += "/" + addr.TemporalSegment } if addr.Path != "" { uri += addr.Path } if addr.Query != "" { uri += "?" + addr.Query } if addr.Fragment != "" { uri += "#" + addr.Fragment } return uri } // ToStorageKey generates a storage key for this address func (addr *UCXLAddress) ToStorageKey() string { key := fmt.Sprintf("%s/%s/%s/%s", addr.Agent, addr.Role, addr.Project, addr.Task) if addr.ResolvedTime != nil { key += "/" + addr.ResolvedTime.Format(time.RFC3339) } else if addr.TemporalSegment != "" { key += "/" + addr.TemporalSegment } if addr.Path != "" { key += addr.Path } return key } ``` #### 1.2 Temporal Navigator Interface **File:** `/pkg/temporal/navigator.go` ```go package temporal import ( "time" "github.com/anthonyrawlins/bzzz/pkg/protocol" ) type TemporalNavigator interface { GetLatestTimestamp(addr *protocol.UCXLAddress) (time.Time, error) GetFirstTimestamp(addr *protocol.UCXLAddress) (time.Time, error) NavigateBackward(addr *protocol.UCXLAddress, steps int) (time.Time, error) NavigateForward(addr *protocol.UCXLAddress, steps int) (time.Time, error) GetAtTime(addr *protocol.UCXLAddress, timestamp time.Time) (*protocol.UCXLAddress, error) } type TemporalIndex struct { // Map address patterns to temporal entries entries map[string][]TemporalEntry } type TemporalEntry struct { Timestamp time.Time `json:"timestamp"` Version int64 `json:"version"` Address *protocol.UCXLAddress `json:"address"` Checksum string `json:"checksum"` } ``` ### Week 2: UCXI Interface Server #### 2.1 UCXI Server Implementation **File:** `/pkg/ucxi/server.go` ```go package ucxi import ( "encoding/json" "net/http" "github.com/gorilla/mux" "github.com/anthonyrawlins/bzzz/pkg/protocol" "github.com/anthonyrawlins/bzzz/pkg/storage" "github.com/anthonyrawlins/bzzz/pkg/temporal" ) type UCXIServer struct { contextStore storage.ContextStore temporalNav temporal.TemporalNavigator router *mux.Router port int } // Context entry structure type ContextEntry struct { Address *protocol.UCXLAddress `json:"address"` Content map[string]interface{} `json:"content"` Metadata ContextMetadata `json:"metadata"` Version int64 `json:"version"` Checksum string `json:"checksum"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type ContextMetadata struct { ContentType string `json:"content_type"` Size int64 `json:"size"` Tags []string `json:"tags"` Provenance string `json:"provenance"` Relationships map[string]string `json:"relationships"` } func NewUCXIServer(store storage.ContextStore, nav temporal.TemporalNavigator, port int) *UCXIServer { server := &UCXIServer{ contextStore: store, temporalNav: nav, router: mux.NewRouter(), port: port, } server.setupRoutes() return server } func (s *UCXIServer) setupRoutes() { // UCXI operations s.router.HandleFunc("/ucxi/{agent}:{role}@{project}:{task}/{temporal}/{path:.*}", s.handleGET).Methods("GET") s.router.HandleFunc("/ucxi/{agent}:{role}@{project}:{task}/{temporal}/{path:.*}", s.handlePUT).Methods("PUT") s.router.HandleFunc("/ucxi/{agent}:{role}@{project}:{task}/{temporal}/", s.handlePOST).Methods("POST") s.router.HandleFunc("/ucxi/{agent}:{role}@{project}:{task}/{temporal}/{path:.*}", s.handleDELETE).Methods("DELETE") s.router.HandleFunc("/ucxi/announce", s.handleANNOUNCE).Methods("POST") // Extended operations s.router.HandleFunc("/ucxi/navigate/{direction}", s.handleNAVIGATE).Methods("GET") s.router.HandleFunc("/ucxi/query", s.handleQUERY).Methods("GET") s.router.HandleFunc("/ucxi/subscribe", s.handleSUBSCRIBE).Methods("POST") } func (s *UCXIServer) handleGET(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) // Construct UCXL address from URL parameters address := &protocol.UCXLAddress{ Agent: vars["agent"], Role: vars["role"], Project: vars["project"], Task: vars["task"], TemporalSegment: vars["temporal"], Path: "/" + vars["path"], } // Resolve temporal navigation if err := address.ResolveTemporalSegment(s.temporalNav); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Retrieve context entry, err := s.contextStore.Retrieve(address) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(entry) } func (s *UCXIServer) handlePUT(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var entry ContextEntry if err := json.NewDecoder(r.Body).Decode(&entry); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Construct address address := &protocol.UCXLAddress{ Agent: vars["agent"], Role: vars["role"], Project: vars["project"], Task: vars["task"], TemporalSegment: vars["temporal"], Path: "/" + vars["path"], } entry.Address = address entry.UpdatedAt = time.Now() if err := s.contextStore.Store(address, &entry); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) } // Additional handlers for POST, DELETE, ANNOUNCE, NAVIGATE, QUERY, SUBSCRIBE... ``` ## Phase 2: Decision Graph & SLURP Integration (Weeks 3-6) ### Week 3-4: Decision Node Schema #### 3.1 Decision Node Structure **File:** `/pkg/decisions/schema.go` ```go package decisions import ( "time" "github.com/anthonyrawlins/bzzz/pkg/protocol" ) // DecisionNode represents a structured decision for SLURP ingestion type DecisionNode struct { DecisionID string `json:"decision_id"` UCXLAddress string `json:"ucxl_address"` Timestamp time.Time `json:"timestamp"` AgentID string `json:"agent_id"` DecisionType string `json:"decision_type"` Context DecisionContext `json:"context"` Justification Justification `json:"justification"` Citations []Citation `json:"citations"` Impacts []Impact `json:"impacts"` Metadata DecisionMetadata `json:"metadata"` } type DecisionContext struct { Project string `json:"project"` Task string `json:"task"` Scope string `json:"scope"` Phase string `json:"phase"` Environment string `json:"environment"` Constraints map[string]interface{} `json:"constraints"` } type Justification struct { Reasoning string `json:"reasoning"` AlternativesConsidered []Alternative `json:"alternatives_considered"` Criteria []string `json:"criteria"` Confidence float64 `json:"confidence"` RiskAssessment RiskAssessment `json:"risk_assessment"` TradeOffs map[string]interface{} `json:"trade_offs"` } type Alternative struct { Name string `json:"name"` Description string `json:"description"` Pros []string `json:"pros"` Cons []string `json:"cons"` Score float64 `json:"score"` Rejected bool `json:"rejected"` Reason string `json:"reason"` Metadata map[string]interface{} `json:"metadata"` } type Citation struct { Type string `json:"type"` // "justified_by", "references", "contradicts", "extends" UCXLAddress string `json:"ucxl_address"` Relevance string `json:"relevance"` // "high", "medium", "low" Excerpt string `json:"excerpt"` Strength float64 `json:"strength"` // 0.0 - 1.0 Verified bool `json:"verified"` VerifiedAt *time.Time `json:"verified_at,omitempty"` } type Impact struct { Type string `json:"type"` // "replaces", "modifies", "creates", "deprecates" UCXLAddress string `json:"ucxl_address"` Reason string `json:"reason"` Severity string `json:"severity"` // "low", "medium", "high", "breaking" Affected []string `json:"affected"` Migration *MigrationInfo `json:"migration,omitempty"` Metadata map[string]interface{} `json:"metadata"` } type MigrationInfo struct { Required bool `json:"required"` Automated bool `json:"automated"` Instructions string `json:"instructions"` Timeline string `json:"timeline"` } type RiskAssessment struct { Level string `json:"level"` // "low", "medium", "high" Factors []string `json:"factors"` Mitigation []string `json:"mitigation"` Monitoring []string `json:"monitoring"` Escalation *EscalationInfo `json:"escalation,omitempty"` } type EscalationInfo struct { Triggers []string `json:"triggers"` Contacts []string `json:"contacts"` Procedures []string `json:"procedures"` } type DecisionMetadata struct { SourceRepository string `json:"source_repository"` CommitSHA string `json:"commit_sha"` PullRequestID string `json:"pull_request_id"` ReviewedBy []string `json:"reviewed_by"` ApprovedBy []string `json:"approved_by"` Tags []string `json:"tags"` Priority int `json:"priority"` Visibility string `json:"visibility"` // "public", "internal", "private" ExpiresAt *time.Time `json:"expires_at,omitempty"` CustomFields map[string]interface{} `json:"custom_fields"` } // Decision types enumeration const ( DecisionTypeArchitecture = "architecture_choice" DecisionTypeImplementation = "implementation_approach" DecisionTypeTechnology = "technology_selection" DecisionTypeProcess = "process_definition" DecisionTypeAPI = "api_design" DecisionTypeDataModel = "data_model_design" DecisionTypeSecurity = "security_requirement" DecisionTypeDeployment = "deployment_strategy" DecisionTypeRollback = "rollback_decision" DecisionTypeDeprecation = "deprecation_notice" ) // Citation types enumeration const ( CitationJustifiedBy = "justified_by" CitationReferences = "references" CitationContradicts = "contradicts" CitationExtends = "extends" CitationSupersedes = "supersedes" ) // Validation methods func (dn *DecisionNode) Validate() error { if dn.DecisionID == "" { return fmt.Errorf("decision_id is required") } if dn.UCXLAddress == "" { return fmt.Errorf("ucxl_address is required") } if _, err := protocol.ParseUCXLAddress(dn.UCXLAddress); err != nil { return fmt.Errorf("invalid ucxl_address: %w", err) } if dn.AgentID == "" { return fmt.Errorf("agent_id is required") } if dn.DecisionType == "" { return fmt.Errorf("decision_type is required") } // Validate citations for i, citation := range dn.Citations { if citation.UCXLAddress == "" { return fmt.Errorf("citation[%d] missing ucxl_address", i) } if _, err := protocol.ParseUCXLAddress(citation.UCXLAddress); err != nil { return fmt.Errorf("citation[%d] invalid ucxl_address: %w", i, err) } } return nil } func (dn *DecisionNode) GenerateID() string { hash := sha256.Sum256([]byte(dn.UCXLAddress + dn.AgentID + dn.Timestamp.Format(time.RFC3339))) return fmt.Sprintf("%x", hash)[:16] } ``` ### Week 5-6: SLURP Integration #### 5.1 SLURP Client Implementation **File:** `/pkg/integration/slurp_client.go` ```go package integration import ( "bytes" "encoding/json" "fmt" "net/http" "time" "github.com/anthonyrawlins/bzzz/pkg/decisions" ) type SLURPClient struct { baseURL string apiKey string httpClient *http.Client batchSize int timeout time.Duration } type SLURPPublishRequest struct { Decisions []decisions.DecisionNode `json:"decisions"` Source string `json:"source"` Version string `json:"version"` Timestamp time.Time `json:"timestamp"` } type SLURPPublishResponse struct { Accepted []string `json:"accepted"` Rejected []string `json:"rejected"` Errors []string `json:"errors"` } func NewSLURPClient(baseURL, apiKey string) *SLURPClient { return &SLURPClient{ baseURL: baseURL, apiKey: apiKey, httpClient: &http.Client{ Timeout: 30 * time.Second, }, batchSize: 10, timeout: 30 * time.Second, } } func (sc *SLURPClient) PublishDecisions(nodes []decisions.DecisionNode) (*SLURPPublishResponse, error) { // Validate all decisions before publishing for i, node := range nodes { if err := node.Validate(); err != nil { return nil, fmt.Errorf("decision[%d] validation failed: %w", i, err) } } request := SLURPPublishRequest{ Decisions: nodes, Source: "bzzz-v2", Version: "2.0.0", Timestamp: time.Now(), } jsonData, err := json.Marshal(request) if err != nil { return nil, fmt.Errorf("failed to marshal request: %w", err) } req, err := http.NewRequest("POST", sc.baseURL+"/api/v1/decisions", bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+sc.apiKey) req.Header.Set("User-Agent", "bzzz-v2/2.0.0") resp, err := sc.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("SLURP API error: %d", resp.StatusCode) } var response SLURPPublishResponse if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { return nil, fmt.Errorf("failed to decode response: %w", err) } return &response, nil } func (sc *SLURPClient) QueryDecisions(query string) ([]decisions.DecisionNode, error) { req, err := http.NewRequest("GET", sc.baseURL+"/api/v1/decisions/query", nil) if err != nil { return nil, err } q := req.URL.Query() q.Add("q", query) req.URL.RawQuery = q.Encode() req.Header.Set("Authorization", "Bearer "+sc.apiKey) resp, err := sc.httpClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var nodes []decisions.DecisionNode if err := json.NewDecoder(resp.Body).Decode(&nodes); err != nil { return nil, err } return nodes, nil } ``` ## Phase 3: Agent Integration & Testing (Weeks 7-8) ### Week 7: GPT-4 Agent UCXL Integration #### 7.1 Updated MCP Tools **File:** `/mcp-server/src/tools/ucxi-tools.ts` ```typescript import { Tool } from "@modelcontextprotocol/sdk/types.js"; export const ucxiTools: Record = { ucxi_get: { name: "ucxi_get", description: "Retrieve context from UCXL address with temporal navigation", inputSchema: { type: "object", properties: { address: { type: "string", description: "UCXL address (e.g., ucxl://gpt4:architect@bzzz:v2/*^/decisions.json)" }, temporal: { type: "string", enum: ["~~", "^^", "*^", "*~"], description: "Temporal navigation: ~~ (back), ^^ (forward), *^ (latest), *~ (first)" } }, required: ["address"] } }, ucxi_put: { name: "ucxi_put", description: "Store context at UCXL address", inputSchema: { type: "object", properties: { address: { type: "string", description: "UCXL address where to store context" }, content: { type: "object", description: "Context content to store" }, metadata: { type: "object", properties: { content_type: { type: "string" }, tags: { type: "array", items: { type: "string" } }, provenance: { type: "string" } }, description: "Context metadata" } }, required: ["address", "content"] } }, ucxi_publish_decision: { name: "ucxi_publish_decision", description: "Publish a structured decision to SLURP via UCXI", inputSchema: { type: "object", properties: { decision_type: { type: "string", enum: ["architecture_choice", "implementation_approach", "technology_selection", "api_design"], description: "Type of decision being published" }, reasoning: { type: "string", description: "Detailed reasoning for the decision" }, alternatives: { type: "array", items: { type: "object", properties: { name: { type: "string" }, description: { type: "string" }, pros: { type: "array", items: { type: "string" } }, cons: { type: "array", items: { type: "string" } }, rejected: { type: "boolean" }, reason: { type: "string" } } }, description: "Alternative approaches considered" }, citations: { type: "array", items: { type: "object", properties: { type: { type: "string", enum: ["justified_by", "references", "contradicts"] }, ucxl_address: { type: "string" }, relevance: { type: "string", enum: ["high", "medium", "low"] }, excerpt: { type: "string" } } }, description: "Citations supporting the decision" }, impacts: { type: "array", items: { type: "object", properties: { type: { type: "string", enum: ["replaces", "modifies", "creates", "deprecates"] }, ucxl_address: { type: "string" }, reason: { type: "string" }, severity: { type: "string", enum: ["low", "medium", "high", "breaking"] } } }, description: "Impacts of this decision" } }, required: ["decision_type", "reasoning"] } }, ucxi_query: { name: "ucxi_query", description: "Query contexts matching UCXL address pattern", inputSchema: { type: "object", properties: { pattern: { type: "string", description: "UCXL address pattern with wildcards (e.g., any:architect@bzzz:*)" }, temporal_range: { type: "object", properties: { start: { type: "string", format: "date-time" }, end: { type: "string", format: "date-time" } }, description: "Temporal range for search" }, content_filter: { type: "string", description: "Full-text search filter for content" } }, required: ["pattern"] } }, ucxi_navigate: { name: "ucxi_navigate", description: "Navigate temporally through context history", inputSchema: { type: "object", properties: { current_address: { type: "string", description: "Current UCXL address position" }, direction: { type: "string", enum: ["~~", "^^"], description: "Navigation direction: ~~ (backward) or ^^ (forward)" }, steps: { type: "integer", default: 1, description: "Number of temporal steps to navigate" } }, required: ["current_address", "direction"] } }, ucxi_announce: { name: "ucxi_announce", description: "Announce context availability to P2P network", inputSchema: { type: "object", properties: { address: { type: "string", description: "UCXL address to announce" }, capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities (roles, specializations)" }, metadata: { type: "object", description: "Additional metadata about the context" } }, required: ["address"] } } }; // Handler implementations export async function handleUCXITool(name: string, args: any): Promise { const ucxiServerURL = process.env.UCXI_SERVER_URL || "http://localhost:8080"; switch (name) { case "ucxi_get": return await ucxiGet(ucxiServerURL, args.address, args.temporal); case "ucxi_put": return await ucxiPut(ucxiServerURL, args.address, args.content, args.metadata); case "ucxi_publish_decision": return await ucxiPublishDecision(ucxiServerURL, args); case "ucxi_query": return await ucxiQuery(ucxiServerURL, args.pattern, args.temporal_range, args.content_filter); case "ucxi_navigate": return await ucxiNavigate(ucxiServerURL, args.current_address, args.direction, args.steps); case "ucxi_announce": return await ucxiAnnounce(ucxiServerURL, args.address, args.capabilities, args.metadata); default: throw new Error(`Unknown UCXI tool: ${name}`); } } async function ucxiGet(serverURL: string, address: string, temporal?: string): Promise { const url = new URL(`/ucxi/${address}`, serverURL); if (temporal) { url.searchParams.set('temporal', temporal); } const response = await fetch(url.toString()); if (!response.ok) { throw new Error(`UCXI GET failed: ${response.status}`); } return await response.json(); } async function ucxiPublishDecision(serverURL: string, decision: any): Promise { const response = await fetch(`${serverURL}/ucxi/decisions/publish`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(decision) }); if (!response.ok) { throw new Error(`Decision publishing failed: ${response.status}`); } return await response.json(); } ``` ### Week 8: Integration Testing #### 8.1 End-to-End Test Suite **File:** `/test/integration/ucxl_e2e_test.go` ```go package integration import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/anthonyrawlins/bzzz/pkg/protocol" "github.com/anthonyrawlins/bzzz/pkg/ucxi" "github.com/anthonyrawlins/bzzz/pkg/decisions" ) func TestUCXLE2E(t *testing.T) { // Start UCXI server server := setupTestServer(t) defer server.Close() t.Run("AddressParsingAndResolution", func(t *testing.T) { // Test UCXL address parsing addr, err := protocol.ParseUCXLAddress("ucxl://gpt4:architect@bzzz:v2/*^/decisions/protocol.json") assert.NoError(t, err) assert.Equal(t, "gpt4", addr.Agent) assert.Equal(t, "architect", addr.Role) assert.Equal(t, "bzzz", addr.Project) assert.Equal(t, "v2", addr.Task) assert.Equal(t, "*^", addr.TemporalSegment) assert.Equal(t, "/decisions/protocol.json", addr.Path) // Test storage key generation storageKey := addr.ToStorageKey() assert.Contains(t, storageKey, "gpt4/architect/bzzz/v2") }) t.Run("TemporalNavigation", func(t *testing.T) { // Create temporal sequence baseAddr := "ucxl://gpt4:architect@bzzz:v2" // Store contexts at different times times := []time.Time{ time.Now().Add(-2 * time.Hour), time.Now().Add(-1 * time.Hour), time.Now(), } for i, timestamp := range times { addr := fmt.Sprintf("%s/%s/decisions/protocol.json", baseAddr, timestamp.Format(time.RFC3339)) content := map[string]interface{}{ "version": i + 1, "decision": fmt.Sprintf("Protocol decision v%d", i+1), } err := storeContext(server, addr, content) assert.NoError(t, err) } // Test latest navigation (*^) latestAddr := fmt.Sprintf("%s/*^/decisions/protocol.json", baseAddr) entry, err := getContext(server, latestAddr) assert.NoError(t, err) assert.Equal(t, 3, entry.Content["version"]) // Test first navigation (*~) firstAddr := fmt.Sprintf("%s/*~/decisions/protocol.json", baseAddr) entry, err = getContext(server, firstAddr) assert.NoError(t, err) assert.Equal(t, 1, entry.Content["version"]) }) t.Run("DecisionPublishing", func(t *testing.T) { // Create decision node decision := &decisions.DecisionNode{ DecisionID: "test-decision-001", UCXLAddress: "ucxl://gpt4:architect@bzzz:v2/2025-08-07T14:30:00Z/decisions/architecture.json", Timestamp: time.Now(), AgentID: "gpt4-test-agent", DecisionType: decisions.DecisionTypeArchitecture, Context: decisions.DecisionContext{ Project: "bzzz", Task: "v2-migration", Scope: "protocol-selection", }, Justification: decisions.Justification{ Reasoning: "UCXL provides superior semantic addressing and temporal navigation capabilities", AlternativesConsidered: []decisions.Alternative{ { Name: "Extend bzzz:// protocol", Description: "Add temporal navigation to existing protocol", Pros: []string{"Minimal changes", "Backward compatibility"}, Cons: []string{"Limited semantic expressiveness", "Technical debt"}, Rejected: true, Reason: "Insufficient semantic richness for complex context addressing", }, }, Criteria: []string{"semantic_richness", "temporal_navigation", "ecosystem_compatibility"}, Confidence: 0.9, }, Citations: []decisions.Citation{ { Type: decisions.CitationJustifiedBy, UCXLAddress: "ucxl://any:any@chorus:requirements/*~/analysis.md", Relevance: "high", Excerpt: "System must support temporal context navigation for audit trails", Strength: 0.95, }, }, Impacts: []decisions.Impact{ { Type: "replaces", UCXLAddress: "ucxl://any:any@bzzz:v1/*^/protocol.go", Reason: "Migrating from bzzz:// to ucxl:// addressing scheme", Severity: "breaking", Affected: []string{"protocol", "addressing", "navigation"}, }, }, } // Validate decision err := decision.Validate() assert.NoError(t, err) // Test decision publishing to SLURP slurpClient := setupMockSLURPClient(t) response, err := slurpClient.PublishDecisions([]decisions.DecisionNode{*decision}) assert.NoError(t, err) assert.Contains(t, response.Accepted, decision.DecisionID) }) t.Run("P2PResolution", func(t *testing.T) { // Test distributed address resolution addr := "ucxl://any:architect@bzzz:*/*^/decisions" // Query should return contexts from multiple agents entries, err := queryContexts(server, addr) assert.NoError(t, err) assert.Greater(t, len(entries), 0) // Test wildcard matching for _, entry := range entries { assert.Equal(t, "architect", entry.Address.Role) assert.Equal(t, "bzzz", entry.Address.Project) } }) t.Run("CitationValidation", func(t *testing.T) { // Test citation chain validation validator := decisions.NewCitationValidator(server.ContextStore) decision := &decisions.DecisionNode{ Citations: []decisions.Citation{ { Type: decisions.CitationJustifiedBy, UCXLAddress: "ucxl://nonexistent:agent@invalid:project/*^/missing.json", Relevance: "high", }, }, } err := validator.ValidateCitations(decision) assert.Error(t, err) // Should fail due to nonexistent citation // Test valid citation decision.Citations[0].UCXLAddress = "ucxl://gpt4:architect@bzzz:v2/*^/requirements.json" // Store the referenced context storeContext(server, decision.Citations[0].UCXLAddress, map[string]interface{}{ "requirement": "temporal navigation support", }) err = validator.ValidateCitations(decision) assert.NoError(t, err) }) } ``` ## Database Schema & Storage ### Context Storage Schema (BadgerDB) ```go // Storage keys const ( ContextKeyPrefix = "ctx:" // ctx:agent/role/project/task/timestamp/path TemporalKeyPrefix = "tmp:" // tmp:agent/role/project/task -> []TemporalEntry IndexKeyPrefix = "idx:" // idx:field:value -> []address MetadataKeyPrefix = "meta:" // meta:address -> ContextMetadata ) // Indexed fields for efficient querying var IndexedFields = []string{ "agent", "role", "project", "task", "content_type", "tags", "timestamp", } // Key generation functions func GenerateContextKey(addr *protocol.UCXLAddress) string { return ContextKeyPrefix + addr.ToStorageKey() } func GenerateTemporalKey(addr *protocol.UCXLAddress) string { return fmt.Sprintf("%s%s/%s/%s/%s", TemporalKeyPrefix, addr.Agent, addr.Role, addr.Project, addr.Task) } ``` This implementation roadmap provides the complete foundation for transforming BZZZ v2 into a UCXL-based semantic context publishing system while maintaining its distributed P2P architecture and integrating seamlessly with the CHORUS infrastructure. ## Key Files Created: - `/home/tony/chorus/project-queues/active/BZZZ/BZZZ_V2_UCXL_DEVELOPMENT_PLAN.md` - `/home/tony/chorus/project-queues/active/BZZZ/TECHNICAL_ARCHITECTURE.md` - `/home/tony/chorus/project-queues/active/BZZZ/IMPLEMENTATION_ROADMAP.md` The roadmap shows exactly how to implement UCXL address parsing, temporal navigation, decision node publishing to SLURP, P2P DHT resolution, and MCP integration with detailed code examples and test suites.