Complete BZZZ functionality port to CHORUS
🎭 CHORUS now contains full BZZZ functionality adapted for containers Core systems ported: - P2P networking (libp2p with DHT and PubSub) - Task coordination (COOEE protocol) - HMMM collaborative reasoning - SHHH encryption and security - SLURP admin election system - UCXL content addressing - UCXI server integration - Hypercore logging system - Health monitoring and graceful shutdown - License validation with KACHING Container adaptations: - Environment variable configuration (no YAML files) - Container-optimized logging to stdout/stderr - Auto-generated agent IDs for container deployments - Docker-first architecture All proven BZZZ P2P protocols, AI integration, and collaboration features are now available in containerized form. Next: Build and test container deployment. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
64
pkg/slurp/context/doc.go
Normal file
64
pkg/slurp/context/doc.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Package context provides core context types and interfaces for the SLURP contextual intelligence system.
|
||||
//
|
||||
// This package defines the foundational data structures and interfaces for hierarchical
|
||||
// context resolution within the BZZZ distributed AI development system. It implements
|
||||
// bounded hierarchy traversal with role-based access control for efficient context
|
||||
// resolution and caching.
|
||||
//
|
||||
// Key Features:
|
||||
// - Hierarchical context resolution with bounded traversal depth
|
||||
// - Role-based access control and encryption for context data
|
||||
// - CSS-like inheritance patterns for cascading context properties
|
||||
// - Efficient caching with selective invalidation
|
||||
// - Integration with BZZZ election system for leader-only generation
|
||||
//
|
||||
// Core Types:
|
||||
// - ContextNode: Represents a single context entry in the hierarchy
|
||||
// - ResolvedContext: Final resolved context output with metadata
|
||||
// - RoleAccessLevel: Defines encryption levels for different roles
|
||||
// - EncryptedContext: Role-encrypted context data for DHT storage
|
||||
//
|
||||
// Primary Interfaces:
|
||||
// - ContextResolver: Main interface for hierarchical context resolution
|
||||
// - HierarchyManager: Manages the context hierarchy structure
|
||||
// - GlobalContextManager: Manages system-wide applicable contexts
|
||||
//
|
||||
// Integration Points:
|
||||
// - pkg/election: Leader election for context generation duties
|
||||
// - pkg/crypto: Role-based encryption and access control
|
||||
// - pkg/dht: Distributed storage of encrypted context data
|
||||
// - pkg/ucxl: UCXL address parsing and handling
|
||||
//
|
||||
// Example Usage:
|
||||
//
|
||||
// resolver := context.NewDefaultResolver(storage, crypto)
|
||||
// ctx := context.Background()
|
||||
//
|
||||
// // Resolve context for a UCXL address with bounded depth
|
||||
// resolved, err := resolver.ResolveWithDepth(ctx, "ucxl://project/src/main.go", 5)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// fmt.Printf("Resolved context: %s\n", resolved.Summary)
|
||||
// fmt.Printf("Technologies: %v\n", resolved.Technologies)
|
||||
// fmt.Printf("Inheritance chain: %v\n", resolved.InheritanceChain)
|
||||
//
|
||||
// Architecture Design:
|
||||
// The context system uses a tree-like hierarchy where child contexts inherit
|
||||
// and override properties from their parents, similar to CSS cascading rules.
|
||||
// This enables efficient context resolution while maintaining consistency
|
||||
// and reducing duplication across the system.
|
||||
//
|
||||
// Performance Considerations:
|
||||
// - Bounded traversal prevents infinite loops and limits resource usage
|
||||
// - Caching with TTL reduces repeated resolution overhead
|
||||
// - Batch operations optimize multi-address resolution
|
||||
// - Role-based filtering reduces unnecessary data transfer
|
||||
//
|
||||
// Security Model:
|
||||
// All context data is encrypted based on role access levels before storage
|
||||
// in the distributed DHT. Only nodes with appropriate role permissions can
|
||||
// decrypt and access context information, ensuring secure context sharing
|
||||
// across the BZZZ cluster.
|
||||
package context
|
||||
528
pkg/slurp/context/resolver.go
Normal file
528
pkg/slurp/context/resolver.go
Normal file
@@ -0,0 +1,528 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"chorus.services/bzzz/pkg/ucxl"
|
||||
"chorus.services/bzzz/pkg/config"
|
||||
)
|
||||
|
||||
// ContextResolver defines the interface for hierarchical context resolution
|
||||
//
|
||||
// The resolver implements bounded hierarchy traversal with caching and
|
||||
// role-based access control, providing efficient context resolution for
|
||||
// UCXL addresses through cascading inheritance patterns.
|
||||
type ContextResolver interface {
|
||||
// Resolve resolves context for a UCXL address using bounded hierarchy traversal
|
||||
// with default depth limits and role-based access control
|
||||
Resolve(ctx context.Context, address ucxl.Address, role string) (*ResolvedContext, error)
|
||||
|
||||
// ResolveWithDepth resolves context with custom bounded depth limit
|
||||
// providing fine-grained control over hierarchy traversal depth for
|
||||
// performance optimization and resource management
|
||||
ResolveWithDepth(ctx context.Context, address ucxl.Address, role string, maxDepth int) (*ResolvedContext, error)
|
||||
|
||||
// BatchResolve efficiently resolves multiple UCXL addresses in parallel
|
||||
// uses request deduplication, shared caching, and role-based filtering
|
||||
// for optimal performance with bulk operations
|
||||
BatchResolve(ctx context.Context, request *BatchResolutionRequest) (*BatchResolutionResult, error)
|
||||
|
||||
// AddGlobalContext adds a global context that applies to all addresses
|
||||
// global contexts are automatically merged into all resolution results
|
||||
AddGlobalContext(ctx context.Context, globalCtx *ContextNode) error
|
||||
|
||||
// SetHierarchyDepthLimit sets the maximum hierarchy depth for bounded traversal
|
||||
// prevents infinite loops and controls resource usage during resolution
|
||||
SetHierarchyDepthLimit(maxDepth int)
|
||||
|
||||
// GetResolutionStatistics returns resolver performance and operational statistics
|
||||
GetStatistics() *ResolutionStatistics
|
||||
|
||||
// InvalidateCache invalidates cached resolutions for an address pattern
|
||||
// useful for cache invalidation when contexts change
|
||||
InvalidateCache(pattern string) error
|
||||
|
||||
// ClearCache clears all cached resolutions
|
||||
ClearCache() error
|
||||
}
|
||||
|
||||
// HierarchyManager manages the context hierarchy with bounded traversal
|
||||
//
|
||||
// Provides operations for maintaining the hierarchical structure of
|
||||
// context nodes while enforcing depth limits and consistency constraints.
|
||||
type HierarchyManager interface {
|
||||
// LoadHierarchy loads the context hierarchy from storage
|
||||
LoadHierarchy(ctx context.Context) error
|
||||
|
||||
// AddNode adds a context node to the hierarchy with validation
|
||||
AddNode(ctx context.Context, node *ContextNode) error
|
||||
|
||||
// UpdateNode updates an existing context node
|
||||
UpdateNode(ctx context.Context, node *ContextNode) error
|
||||
|
||||
// RemoveNode removes a context node and handles orphaned children
|
||||
RemoveNode(ctx context.Context, path string) error
|
||||
|
||||
// GetNode retrieves a context node by path
|
||||
GetNode(ctx context.Context, path string) (*ContextNode, error)
|
||||
|
||||
// TraverseUp traverses up the hierarchy with bounded depth
|
||||
TraverseUp(ctx context.Context, startPath string, maxDepth int) ([]*ContextNode, error)
|
||||
|
||||
// TraverseDown traverses down the hierarchy with bounded depth
|
||||
TraverseDown(ctx context.Context, startPath string, maxDepth int) ([]*ContextNode, error)
|
||||
|
||||
// GetChildren gets immediate children of a node
|
||||
GetChildren(ctx context.Context, path string) ([]*ContextNode, error)
|
||||
|
||||
// GetParent gets the immediate parent of a node
|
||||
GetParent(ctx context.Context, path string) (*ContextNode, error)
|
||||
|
||||
// ValidateHierarchy validates hierarchy integrity and constraints
|
||||
ValidateHierarchy(ctx context.Context) error
|
||||
|
||||
// GetHierarchyStats returns statistics about the hierarchy
|
||||
GetHierarchyStats(ctx context.Context) (*HierarchyStats, error)
|
||||
}
|
||||
|
||||
// GlobalContextManager manages global contexts that apply everywhere
|
||||
//
|
||||
// Global contexts provide system-wide applicable metadata that is
|
||||
// automatically included in all context resolutions regardless of
|
||||
// hierarchy position.
|
||||
type GlobalContextManager interface {
|
||||
// AddGlobalContext adds a context that applies globally
|
||||
AddGlobalContext(ctx context.Context, globalCtx *ContextNode) error
|
||||
|
||||
// RemoveGlobalContext removes a global context
|
||||
RemoveGlobalContext(ctx context.Context, contextID string) error
|
||||
|
||||
// UpdateGlobalContext updates an existing global context
|
||||
UpdateGlobalContext(ctx context.Context, globalCtx *ContextNode) error
|
||||
|
||||
// ListGlobalContexts lists all global contexts ordered by priority
|
||||
ListGlobalContexts(ctx context.Context) ([]*ContextNode, error)
|
||||
|
||||
// GetGlobalContext retrieves a specific global context
|
||||
GetGlobalContext(ctx context.Context, contextID string) (*ContextNode, error)
|
||||
|
||||
// ApplyGlobalContexts applies global contexts to a resolution
|
||||
ApplyGlobalContexts(ctx context.Context, resolved *ResolvedContext) error
|
||||
|
||||
// EnableGlobalContext enables/disables a global context
|
||||
EnableGlobalContext(ctx context.Context, contextID string, enabled bool) error
|
||||
|
||||
// SetGlobalContextPriority sets priority for global context application
|
||||
SetGlobalContextPriority(ctx context.Context, contextID string, priority int) error
|
||||
}
|
||||
|
||||
// CacheManager manages caching for context resolution performance
|
||||
type CacheManager interface {
|
||||
// Get retrieves a cached resolution
|
||||
Get(ctx context.Context, key string) (*ResolvedContext, error)
|
||||
|
||||
// Set stores a resolution in cache with TTL
|
||||
Set(ctx context.Context, key string, resolved *ResolvedContext, ttl time.Duration) error
|
||||
|
||||
// Delete removes a specific cache entry
|
||||
Delete(ctx context.Context, key string) error
|
||||
|
||||
// DeletePattern removes cache entries matching a pattern
|
||||
DeletePattern(ctx context.Context, pattern string) error
|
||||
|
||||
// Clear clears all cached entries
|
||||
Clear(ctx context.Context) error
|
||||
|
||||
// GetStats returns cache performance statistics
|
||||
GetStats() *CacheStats
|
||||
}
|
||||
|
||||
// CacheStats represents cache performance statistics
|
||||
type CacheStats struct {
|
||||
HitRate float64 `json:"hit_rate"` // Cache hit rate (0-1)
|
||||
MissRate float64 `json:"miss_rate"` // Cache miss rate (0-1)
|
||||
TotalHits int64 `json:"total_hits"` // Total cache hits
|
||||
TotalMisses int64 `json:"total_misses"` // Total cache misses
|
||||
CurrentSize int64 `json:"current_size"` // Current cache size
|
||||
MaxSize int64 `json:"max_size"` // Maximum cache size
|
||||
Evictions int64 `json:"evictions"` // Number of cache evictions
|
||||
LastEviction time.Time `json:"last_eviction"` // When last eviction occurred
|
||||
}
|
||||
|
||||
// ContextMerger handles merging contexts during resolution
|
||||
type ContextMerger interface {
|
||||
// MergeContexts merges multiple contexts using inheritance rules
|
||||
MergeContexts(contexts []*ContextNode, options *MergeOptions) (*ResolvedContext, error)
|
||||
|
||||
// MergeWithGlobal merges context with global contexts
|
||||
MergeWithGlobal(base *ResolvedContext, globals []*ContextNode) (*ResolvedContext, error)
|
||||
|
||||
// CalculateSpecificity calculates context specificity for merge priority
|
||||
CalculateSpecificity(ctx *ContextNode) int
|
||||
|
||||
// ValidateMergeResult validates merged context quality
|
||||
ValidateMergeResult(resolved *ResolvedContext) (*ValidationResult, error)
|
||||
}
|
||||
|
||||
// ContextValidator validates context data quality and consistency
|
||||
type ContextValidator interface {
|
||||
// ValidateNode validates a single context node
|
||||
ValidateNode(ctx context.Context, node *ContextNode) (*ValidationResult, error)
|
||||
|
||||
// ValidateResolved validates a resolved context
|
||||
ValidateResolved(ctx context.Context, resolved *ResolvedContext) (*ValidationResult, error)
|
||||
|
||||
// ValidateHierarchyConsistency validates hierarchy-wide consistency
|
||||
ValidateHierarchyConsistency(ctx context.Context) ([]*ValidationIssue, error)
|
||||
|
||||
// SuggestImprovements suggests improvements for context quality
|
||||
SuggestImprovements(ctx context.Context, node *ContextNode) ([]string, error)
|
||||
}
|
||||
|
||||
// Helper functions and integration examples
|
||||
|
||||
// ValidateContextResolutionRequest validates a context resolution request
|
||||
func ValidateContextResolutionRequest(address ucxl.Address, role string, maxDepth int) error {
|
||||
if err := address.Validate(); err != nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidAddress,
|
||||
"invalid UCXL address in resolution request").WithUnderlying(err).WithAddress(address)
|
||||
}
|
||||
|
||||
if role == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidRole,
|
||||
"role cannot be empty in resolution request").WithAddress(address)
|
||||
}
|
||||
|
||||
if maxDepth < 0 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeDepthExceeded,
|
||||
"maxDepth cannot be negative").WithAddress(address).
|
||||
WithContext("max_depth", fmt.Sprintf("%d", maxDepth))
|
||||
}
|
||||
|
||||
if maxDepth > 50 { // Reasonable upper bound to prevent resource exhaustion
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeDepthExceeded,
|
||||
"maxDepth exceeds reasonable limits").WithAddress(address).
|
||||
WithContext("max_depth", fmt.Sprintf("%d", maxDepth))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBatchResolutionRequest validates a batch resolution request
|
||||
func ValidateBatchResolutionRequest(request *BatchResolutionRequest) error {
|
||||
if request == nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"batch resolution request cannot be nil")
|
||||
}
|
||||
|
||||
if len(request.Addresses) == 0 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"batch resolution request must contain at least one address")
|
||||
}
|
||||
|
||||
if len(request.Addresses) > 100 { // Prevent excessive batch sizes
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"batch resolution request exceeds maximum size").
|
||||
WithContext("size", fmt.Sprintf("%d", len(request.Addresses)))
|
||||
}
|
||||
|
||||
for i, address := range request.Addresses {
|
||||
if err := address.Validate(); err != nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidAddress,
|
||||
fmt.Sprintf("invalid address at index %d", i)).WithUnderlying(err).WithAddress(address)
|
||||
}
|
||||
}
|
||||
|
||||
if request.Role == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidRole,
|
||||
"role cannot be empty in batch resolution request")
|
||||
}
|
||||
|
||||
if request.MaxDepth < 0 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeDepthExceeded,
|
||||
"maxDepth cannot be negative in batch resolution request").
|
||||
WithContext("max_depth", fmt.Sprintf("%d", request.MaxDepth))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CalculateResolutionConfidence calculates overall confidence from multiple context nodes
|
||||
func CalculateResolutionConfidence(contexts []*ContextNode) float64 {
|
||||
if len(contexts) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
totalConfidence := 0.0
|
||||
totalWeight := 0.0
|
||||
|
||||
for _, ctx := range contexts {
|
||||
// Weight by specificity - higher specificity contexts have more influence
|
||||
weight := float64(ctx.ContextSpecificity + 1)
|
||||
totalConfidence += ctx.RAGConfidence * weight
|
||||
totalWeight += weight
|
||||
}
|
||||
|
||||
if totalWeight == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
confidence := totalConfidence / totalWeight
|
||||
|
||||
// Apply diminishing returns for multiple contexts
|
||||
if len(contexts) > 1 {
|
||||
// Slight boost for having multiple confirming contexts, but not linear
|
||||
multiplier := 1.0 + (float64(len(contexts)-1) * 0.1)
|
||||
confidence = confidence * multiplier
|
||||
if confidence > 1.0 {
|
||||
confidence = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
return confidence
|
||||
}
|
||||
|
||||
// FilterContextsByRole filters context nodes based on role access
|
||||
func FilterContextsByRole(contexts []*ContextNode, role string, authority config.AuthorityLevel) []*ContextNode {
|
||||
filtered := make([]*ContextNode, 0, len(contexts))
|
||||
|
||||
for _, ctx := range contexts {
|
||||
if ctx.CanAccess(role, authority) {
|
||||
filtered = append(filtered, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
// MergeStringSlices merges multiple string slices with deduplication
|
||||
func MergeStringSlices(slices ...[]string) []string {
|
||||
seen := make(map[string]bool)
|
||||
var result []string
|
||||
|
||||
for _, slice := range slices {
|
||||
for _, item := range slice {
|
||||
if !seen[item] && item != "" {
|
||||
seen[item] = true
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// BuildInheritanceChain builds the inheritance chain for a resolved context
|
||||
func BuildInheritanceChain(contexts []*ContextNode) []string {
|
||||
chain := make([]string, 0, len(contexts))
|
||||
|
||||
// Sort by specificity (most specific first)
|
||||
for _, ctx := range contexts {
|
||||
chain = append(chain, ctx.Path)
|
||||
}
|
||||
|
||||
return chain
|
||||
}
|
||||
|
||||
// GenerateCacheKey generates a cache key for resolution requests
|
||||
func GenerateCacheKey(address ucxl.Address, role string, maxDepth int) string {
|
||||
return fmt.Sprintf("resolve:%s:%s:%d", address.String(), role, maxDepth)
|
||||
}
|
||||
|
||||
// IsContextStale determines if a context node is stale and needs refresh
|
||||
func IsContextStale(ctx *ContextNode, staleTTL time.Duration) bool {
|
||||
return time.Since(ctx.GeneratedAt) > staleTTL
|
||||
}
|
||||
|
||||
/*
|
||||
Integration Examples:
|
||||
|
||||
1. DHT Integration Example:
|
||||
|
||||
// Store context in DHT with role-based encryption
|
||||
func (resolver *DefaultContextResolver) storeContextInDHT(ctx *ContextNode, roles []string) error {
|
||||
for _, role := range roles {
|
||||
// Encrypt context for role
|
||||
encrypted, err := resolver.crypto.EncryptForRole(ctx, role)
|
||||
if err != nil {
|
||||
return NewContextError(ErrorTypeEncryption, ErrorCodeEncryptionFailed,
|
||||
"failed to encrypt context for role").WithAddress(ctx.UCXLAddress).
|
||||
WithContext("role", role).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// Store in DHT
|
||||
key := fmt.Sprintf("context:%s:%s", ctx.UCXLAddress.String(), role)
|
||||
if err := resolver.dht.Put(key, encrypted); err != nil {
|
||||
return NewContextError(ErrorTypeDHT, ErrorCodeDHTError,
|
||||
"failed to store context in DHT").WithAddress(ctx.UCXLAddress).
|
||||
WithContext("role", role).WithUnderlying(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
2. Leader Election Integration Example:
|
||||
|
||||
// Context generation only happens on leader node
|
||||
func (manager *ContextManager) GenerateContextIfLeader(filePath string, role string) error {
|
||||
if !manager.IsLeader() {
|
||||
return NewContextError(ErrorTypeAccess, ErrorCodeAccessDenied,
|
||||
"context generation is only allowed on leader nodes").
|
||||
WithContext("current_role", "follower")
|
||||
}
|
||||
|
||||
// Parse UCXL address from file path
|
||||
address, err := manager.pathResolver.PathToUCXL(filePath)
|
||||
if err != nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidAddress,
|
||||
"failed to resolve file path to UCXL address").WithUnderlying(err).
|
||||
WithContext("file_path", filePath)
|
||||
}
|
||||
|
||||
// Generate context using intelligence engine
|
||||
ctx, err := manager.intelligence.AnalyzeFile(context.Background(), filePath, role)
|
||||
if err != nil {
|
||||
return NewContextError(ErrorTypeIntelligence, ErrorCodeInternalError,
|
||||
"failed to generate context").WithAddress(*address).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// Store in hierarchy manager
|
||||
if err := manager.hierarchyManager.AddNode(context.Background(), ctx); err != nil {
|
||||
return NewContextError(ErrorTypeHierarchy, ErrorCodeStorageError,
|
||||
"failed to add context to hierarchy").WithAddress(ctx.UCXLAddress).
|
||||
WithUnderlying(err)
|
||||
}
|
||||
|
||||
// Distribute via DHT for role-based access
|
||||
roles := manager.getRolesForContext(ctx)
|
||||
return manager.distributor.DistributeContext(ctx, roles)
|
||||
}
|
||||
|
||||
3. Crypto Integration Example:
|
||||
|
||||
// Decrypt context based on role authority
|
||||
func (resolver *DefaultContextResolver) decryptContextForRole(encrypted []byte, role string) (*ContextNode, error) {
|
||||
// Check if current agent can decrypt this role's content
|
||||
canDecrypt, err := resolver.config.CanDecryptRole(role)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeAccess, ErrorCodeInvalidRole,
|
||||
"failed to check decryption permissions").WithContext("role", role).
|
||||
WithUnderlying(err)
|
||||
}
|
||||
|
||||
if !canDecrypt {
|
||||
return nil, NewContextError(ErrorTypeAccess, ErrorCodeAccessDenied,
|
||||
"insufficient authority to decrypt context").WithContext("role", role).
|
||||
WithContext("current_role", resolver.config.Agent.Role)
|
||||
}
|
||||
|
||||
// Decrypt using role's private key
|
||||
decrypted, err := resolver.crypto.DecryptWithRole(encrypted)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeEncryption, ErrorCodeDecryptionFailed,
|
||||
"failed to decrypt context").WithContext("role", role).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// Deserialize context
|
||||
var ctx ContextNode
|
||||
if err := json.Unmarshal(decrypted, &ctx); err != nil {
|
||||
return nil, NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"failed to deserialize decrypted context").WithUnderlying(err)
|
||||
}
|
||||
|
||||
return &ctx, nil
|
||||
}
|
||||
|
||||
4. Complete Resolution Flow Example:
|
||||
|
||||
// Resolve context with full BZZZ integration
|
||||
func (resolver *DefaultContextResolver) ResolveWithIntegration(ctx context.Context, address ucxl.Address, role string, maxDepth int) (*ResolvedContext, error) {
|
||||
// 1. Validate request
|
||||
if err := ValidateContextResolutionRequest(address, role, maxDepth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. Check cache first
|
||||
cacheKey := GenerateCacheKey(address, role, maxDepth)
|
||||
if cached, err := resolver.cache.Get(ctx, cacheKey); err == nil {
|
||||
resolver.stats.CacheHits++
|
||||
return cached, nil
|
||||
}
|
||||
resolver.stats.CacheMisses++
|
||||
|
||||
// 3. Try local hierarchy first
|
||||
localContexts, err := resolver.hierarchyManager.TraverseUp(ctx, address.Path, maxDepth)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeHierarchy, ErrorCodeStorageError,
|
||||
"failed to traverse local hierarchy").WithAddress(address).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// 4. If no local contexts, try DHT
|
||||
var dhtContexts []*ContextNode
|
||||
if len(localContexts) == 0 {
|
||||
dhtContext, err := resolver.fetchContextFromDHT(address, role)
|
||||
if err == nil {
|
||||
dhtContexts = []*ContextNode{dhtContext}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Combine local and DHT contexts
|
||||
allContexts := append(localContexts, dhtContexts...)
|
||||
if len(allContexts) == 0 {
|
||||
return nil, NewContextError(ErrorTypeResolution, ErrorCodeNotFound,
|
||||
"no context found for address").WithAddress(address)
|
||||
}
|
||||
|
||||
// 6. Filter by role access
|
||||
authority, err := resolver.config.GetRoleAuthority(role)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeAccess, ErrorCodeInvalidRole,
|
||||
"failed to get role authority").WithContext("role", role).WithUnderlying(err)
|
||||
}
|
||||
|
||||
accessibleContexts := FilterContextsByRole(allContexts, role, authority)
|
||||
if len(accessibleContexts) == 0 {
|
||||
return nil, NewContextError(ErrorTypeAccess, ErrorCodeAccessDenied,
|
||||
"no accessible contexts for role").WithAddress(address).WithContext("role", role)
|
||||
}
|
||||
|
||||
// 7. Merge contexts using inheritance rules
|
||||
resolved, err := resolver.merger.MergeContexts(accessibleContexts, resolver.mergeOptions)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeResolution, ErrorCodeInternalError,
|
||||
"failed to merge contexts").WithAddress(address).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// 8. Apply global contexts if enabled
|
||||
if resolver.globalContextsEnabled {
|
||||
globalContexts, err := resolver.globalManager.ListGlobalContexts(ctx)
|
||||
if err == nil && len(globalContexts) > 0 {
|
||||
resolved, err = resolver.merger.MergeWithGlobal(resolved, globalContexts)
|
||||
if err != nil {
|
||||
return nil, NewContextError(ErrorTypeResolution, ErrorCodeInternalError,
|
||||
"failed to apply global contexts").WithAddress(address).WithUnderlying(err)
|
||||
}
|
||||
resolved.GlobalContextsApplied = true
|
||||
}
|
||||
}
|
||||
|
||||
// 9. Validate resolved context
|
||||
if err := resolved.Validate(); err != nil {
|
||||
return nil, NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"resolved context failed validation").WithAddress(address).WithUnderlying(err)
|
||||
}
|
||||
|
||||
// 10. Cache the result
|
||||
if err := resolver.cache.Set(ctx, cacheKey, resolved, resolver.cacheTTL); err != nil {
|
||||
// Log but don't fail the request
|
||||
resolver.logger.Warn("failed to cache resolved context", "error", err)
|
||||
}
|
||||
|
||||
// 11. Update statistics
|
||||
resolver.stats.TotalResolutions++
|
||||
|
||||
return resolved, nil
|
||||
}
|
||||
*/
|
||||
471
pkg/slurp/context/types.go
Normal file
471
pkg/slurp/context/types.go
Normal file
@@ -0,0 +1,471 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"chorus.services/bzzz/pkg/ucxl"
|
||||
"chorus.services/bzzz/pkg/config"
|
||||
)
|
||||
|
||||
// ContextNode represents a hierarchical context node in the SLURP system.
|
||||
//
|
||||
// Context nodes form a tree structure where child nodes inherit and
|
||||
// override properties from their parents. This enables efficient
|
||||
// cascading context resolution with bounded depth traversal.
|
||||
type ContextNode struct {
|
||||
// Identity and addressing
|
||||
Path string `json:"path"` // Filesystem path
|
||||
UCXLAddress ucxl.Address `json:"ucxl_address"` // Associated UCXL address
|
||||
Summary string `json:"summary"` // Brief description
|
||||
Purpose string `json:"purpose"` // What this component does
|
||||
|
||||
// Context metadata
|
||||
Technologies []string `json:"technologies"` // Technologies used
|
||||
Tags []string `json:"tags"` // Categorization tags
|
||||
Insights []string `json:"insights"` // Analytical insights
|
||||
|
||||
// Hierarchy control
|
||||
OverridesParent bool `json:"overrides_parent"` // Whether this overrides parent context
|
||||
ContextSpecificity int `json:"context_specificity"` // Specificity level (higher = more specific)
|
||||
AppliesToChildren bool `json:"applies_to_children"` // Whether this applies to child directories
|
||||
|
||||
// Metadata
|
||||
GeneratedAt time.Time `json:"generated_at"` // When context was generated
|
||||
RAGConfidence float64 `json:"rag_confidence"` // RAG system confidence (0-1)
|
||||
|
||||
// Access control
|
||||
EncryptedFor []string `json:"encrypted_for"` // Roles that can access
|
||||
AccessLevel RoleAccessLevel `json:"access_level"` // Required access level
|
||||
|
||||
// Custom metadata
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"` // Additional metadata
|
||||
}
|
||||
|
||||
// RoleAccessLevel defines encryption levels for different roles
|
||||
// This mirrors the config.AuthorityLevel but adds more granular access control
|
||||
type RoleAccessLevel int
|
||||
|
||||
const (
|
||||
AccessPublic RoleAccessLevel = iota // Anyone can access
|
||||
AccessLow // Basic role access
|
||||
AccessMedium // Coordination role access
|
||||
AccessHigh // Decision role access
|
||||
AccessCritical // Master role access only
|
||||
)
|
||||
|
||||
// EncryptedContext represents role-encrypted context data for DHT storage
|
||||
type EncryptedContext struct {
|
||||
UCXLAddress ucxl.Address `json:"ucxl_address"` // Associated UCXL address
|
||||
Role string `json:"role"` // Target role for access
|
||||
AccessLevel RoleAccessLevel `json:"access_level"` // Required access level
|
||||
EncryptedData []byte `json:"encrypted_data"` // Encrypted context data
|
||||
KeyFingerprint string `json:"key_fingerprint"` // Key identification
|
||||
CreatedAt time.Time `json:"created_at"` // When encrypted
|
||||
}
|
||||
|
||||
// ResolvedContext represents the final resolved context output
|
||||
//
|
||||
// This is the primary output of the context resolution process, combining
|
||||
// information from multiple hierarchy levels and applying global contexts.
|
||||
type ResolvedContext struct {
|
||||
UCXLAddress ucxl.Address `json:"ucxl_address"` // Original UCXL address
|
||||
Summary string `json:"summary"` // Resolved summary
|
||||
Purpose string `json:"purpose"` // Resolved purpose
|
||||
Technologies []string `json:"technologies"` // Merged technologies
|
||||
Tags []string `json:"tags"` // Merged tags
|
||||
Insights []string `json:"insights"` // Merged insights
|
||||
|
||||
// Resolution metadata
|
||||
ContextSourcePath string `json:"context_source_path"` // Primary source context path
|
||||
InheritanceChain []string `json:"inheritance_chain"` // Context inheritance chain
|
||||
ResolutionConfidence float64 `json:"resolution_confidence"` // Overall confidence (0-1)
|
||||
BoundedDepth int `json:"bounded_depth"` // Actual traversal depth used
|
||||
GlobalContextsApplied bool `json:"global_contexts_applied"` // Whether global contexts were applied
|
||||
ResolvedAt time.Time `json:"resolved_at"` // When resolution occurred
|
||||
}
|
||||
|
||||
// ResolutionStatistics represents statistics about context resolution operations
|
||||
type ResolutionStatistics struct {
|
||||
ContextNodes int `json:"context_nodes"` // Total context nodes in hierarchy
|
||||
GlobalContexts int `json:"global_contexts"` // Number of global contexts
|
||||
MaxHierarchyDepth int `json:"max_hierarchy_depth"` // Maximum hierarchy depth allowed
|
||||
CachedResolutions int `json:"cached_resolutions"` // Number of cached resolutions
|
||||
TotalResolutions int `json:"total_resolutions"` // Total resolution operations
|
||||
AverageDepth float64 `json:"average_depth"` // Average traversal depth
|
||||
CacheHitRate float64 `json:"cache_hit_rate"` // Cache hit rate (0-1)
|
||||
LastResetAt time.Time `json:"last_reset_at"` // When stats were last reset
|
||||
}
|
||||
|
||||
// ContextScope defines the scope of a context node's application
|
||||
type ContextScope string
|
||||
|
||||
const (
|
||||
ScopeLocal ContextScope = "local" // Only applies to this specific file/directory
|
||||
ScopeChildren ContextScope = "children" // Applies to this and all child directories
|
||||
ScopeGlobal ContextScope = "global" // Applies to the entire project
|
||||
)
|
||||
|
||||
// HierarchyStats represents statistics about hierarchy operations
|
||||
type HierarchyStats struct {
|
||||
NodesCreated int `json:"nodes_created"` // Number of nodes created
|
||||
NodesUpdated int `json:"nodes_updated"` // Number of nodes updated
|
||||
FilesAnalyzed int `json:"files_analyzed"` // Number of files analyzed
|
||||
DirectoriesScanned int `json:"directories_scanned"` // Number of directories scanned
|
||||
GenerationTime time.Duration `json:"generation_time"` // Time taken for generation
|
||||
AverageConfidence float64 `json:"average_confidence"` // Average confidence score
|
||||
TotalSize int64 `json:"total_size"` // Total size of analyzed content
|
||||
SkippedFiles int `json:"skipped_files"` // Number of files skipped
|
||||
Errors []string `json:"errors"` // Generation errors
|
||||
}
|
||||
|
||||
// CacheEntry represents a cached context resolution
|
||||
type CacheEntry struct {
|
||||
Key string `json:"key"` // Cache key
|
||||
ResolvedCtx *ResolvedContext `json:"resolved_ctx"` // Cached resolved context
|
||||
CreatedAt time.Time `json:"created_at"` // When cached
|
||||
ExpiresAt time.Time `json:"expires_at"` // When cache expires
|
||||
AccessCount int `json:"access_count"` // Number of times accessed
|
||||
LastAccessed time.Time `json:"last_accessed"` // When last accessed
|
||||
}
|
||||
|
||||
// ValidationResult represents the result of context validation
|
||||
type ValidationResult struct {
|
||||
Valid bool `json:"valid"` // Whether context is valid
|
||||
ConfidenceScore float64 `json:"confidence_score"` // Overall confidence (0-1)
|
||||
QualityScore float64 `json:"quality_score"` // Quality assessment (0-1)
|
||||
Issues []*ValidationIssue `json:"issues"` // Validation issues found
|
||||
ValidatedAt time.Time `json:"validated_at"` // When validation occurred
|
||||
ValidatedBy string `json:"validated_by"` // Who/what performed validation
|
||||
}
|
||||
|
||||
// ValidationIssue represents an issue found during validation
|
||||
type ValidationIssue struct {
|
||||
Severity string `json:"severity"` // error, warning, info
|
||||
Message string `json:"message"` // Issue description
|
||||
Field string `json:"field"` // Affected field
|
||||
Suggestion string `json:"suggestion"` // How to fix
|
||||
}
|
||||
|
||||
// MergeOptions defines options for merging contexts during resolution
|
||||
type MergeOptions struct {
|
||||
PreferParent bool `json:"prefer_parent"` // Prefer parent values over child
|
||||
MergeTechnologies bool `json:"merge_technologies"` // Merge technology lists
|
||||
MergeTags bool `json:"merge_tags"` // Merge tag lists
|
||||
MergeInsights bool `json:"merge_insights"` // Merge insight lists
|
||||
ExcludedFields []string `json:"excluded_fields"` // Fields to exclude from merge
|
||||
WeightParentByDepth bool `json:"weight_parent_by_depth"` // Weight parent influence by depth
|
||||
MinConfidenceThreshold float64 `json:"min_confidence_threshold"` // Minimum confidence to include
|
||||
}
|
||||
|
||||
// BatchResolutionRequest represents a batch resolution request
|
||||
type BatchResolutionRequest struct {
|
||||
Addresses []ucxl.Address `json:"addresses"` // UCXL addresses to resolve
|
||||
MaxDepth int `json:"max_depth"` // Maximum traversal depth
|
||||
Role string `json:"role"` // Requesting role for access control
|
||||
Options *MergeOptions `json:"options"` // Merge options
|
||||
}
|
||||
|
||||
// BatchResolutionResult represents the result of batch resolution
|
||||
type BatchResolutionResult struct {
|
||||
Results map[string]*ResolvedContext `json:"results"` // Resolution results by address
|
||||
Errors map[string]error `json:"errors"` // Errors by address
|
||||
ProcessedAt time.Time `json:"processed_at"` // When batch was processed
|
||||
Duration time.Duration `json:"duration"` // Total processing time
|
||||
CacheHits int `json:"cache_hits"` // Number of cache hits
|
||||
CacheMisses int `json:"cache_misses"` // Number of cache misses
|
||||
}
|
||||
|
||||
// ContextError represents a context-related error with structured information
|
||||
type ContextError struct {
|
||||
Type string `json:"type"` // Error type (validation, resolution, access, etc.)
|
||||
Message string `json:"message"` // Human-readable error message
|
||||
Code string `json:"code"` // Machine-readable error code
|
||||
Address *ucxl.Address `json:"address"` // Related UCXL address if applicable
|
||||
Context map[string]string `json:"context"` // Additional context information
|
||||
Underlying error `json:"underlying"` // Underlying error if any
|
||||
}
|
||||
|
||||
func (e *ContextError) Error() string {
|
||||
if e.Address != nil {
|
||||
return fmt.Sprintf("context error [%s:%s] for address %s: %s", e.Type, e.Code, e.Address.String(), e.Message)
|
||||
}
|
||||
return fmt.Sprintf("context error [%s:%s]: %s", e.Type, e.Code, e.Message)
|
||||
}
|
||||
|
||||
func (e *ContextError) Unwrap() error {
|
||||
return e.Underlying
|
||||
}
|
||||
|
||||
// Common error types and codes
|
||||
const (
|
||||
ErrorTypeValidation = "validation"
|
||||
ErrorTypeResolution = "resolution"
|
||||
ErrorTypeAccess = "access"
|
||||
ErrorTypeStorage = "storage"
|
||||
ErrorTypeEncryption = "encryption"
|
||||
ErrorTypeDHT = "dht"
|
||||
ErrorTypeHierarchy = "hierarchy"
|
||||
ErrorTypeCache = "cache"
|
||||
ErrorTypeTemporalGraph = "temporal_graph"
|
||||
ErrorTypeIntelligence = "intelligence"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrorCodeInvalidAddress = "invalid_address"
|
||||
ErrorCodeInvalidContext = "invalid_context"
|
||||
ErrorCodeInvalidRole = "invalid_role"
|
||||
ErrorCodeAccessDenied = "access_denied"
|
||||
ErrorCodeNotFound = "not_found"
|
||||
ErrorCodeDepthExceeded = "depth_exceeded"
|
||||
ErrorCodeCycleDetected = "cycle_detected"
|
||||
ErrorCodeEncryptionFailed = "encryption_failed"
|
||||
ErrorCodeDecryptionFailed = "decryption_failed"
|
||||
ErrorCodeDHTError = "dht_error"
|
||||
ErrorCodeCacheError = "cache_error"
|
||||
ErrorCodeStorageError = "storage_error"
|
||||
ErrorCodeInvalidConfig = "invalid_config"
|
||||
ErrorCodeTimeout = "timeout"
|
||||
ErrorCodeInternalError = "internal_error"
|
||||
)
|
||||
|
||||
// NewContextError creates a new context error with structured information
|
||||
func NewContextError(errorType, code, message string) *ContextError {
|
||||
return &ContextError{
|
||||
Type: errorType,
|
||||
Code: code,
|
||||
Message: message,
|
||||
Context: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// WithAddress adds an address to the error context
|
||||
func (e *ContextError) WithAddress(address ucxl.Address) *ContextError {
|
||||
e.Address = &address
|
||||
return e
|
||||
}
|
||||
|
||||
// WithContext adds contextual information to the error
|
||||
func (e *ContextError) WithContext(key, value string) *ContextError {
|
||||
if e.Context == nil {
|
||||
e.Context = make(map[string]string)
|
||||
}
|
||||
e.Context[key] = value
|
||||
return e
|
||||
}
|
||||
|
||||
// WithUnderlying wraps an underlying error
|
||||
func (e *ContextError) WithUnderlying(err error) *ContextError {
|
||||
e.Underlying = err
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns the string representation of the access level
|
||||
func (ral RoleAccessLevel) String() string {
|
||||
switch ral {
|
||||
case AccessPublic:
|
||||
return "public"
|
||||
case AccessLow:
|
||||
return "low"
|
||||
case AccessMedium:
|
||||
return "medium"
|
||||
case AccessHigh:
|
||||
return "high"
|
||||
case AccessCritical:
|
||||
return "critical"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// ParseRoleAccessLevel parses a string into a RoleAccessLevel
|
||||
func ParseRoleAccessLevel(level string) (RoleAccessLevel, error) {
|
||||
switch level {
|
||||
case "public":
|
||||
return AccessPublic, nil
|
||||
case "low":
|
||||
return AccessLow, nil
|
||||
case "medium":
|
||||
return AccessMedium, nil
|
||||
case "high":
|
||||
return AccessHigh, nil
|
||||
case "critical":
|
||||
return AccessCritical, nil
|
||||
default:
|
||||
return AccessPublic, NewContextError(ErrorTypeValidation, ErrorCodeInvalidRole,
|
||||
fmt.Sprintf("invalid role access level: %s", level))
|
||||
}
|
||||
}
|
||||
|
||||
// AuthorityToAccessLevel converts config.AuthorityLevel to RoleAccessLevel
|
||||
func AuthorityToAccessLevel(authority config.AuthorityLevel) RoleAccessLevel {
|
||||
switch authority {
|
||||
case config.AuthorityMaster:
|
||||
return AccessCritical
|
||||
case config.AuthorityDecision:
|
||||
return AccessHigh
|
||||
case config.AuthorityCoordination:
|
||||
return AccessMedium
|
||||
case config.AuthoritySuggestion:
|
||||
return AccessLow
|
||||
case config.AuthorityReadOnly:
|
||||
return AccessPublic
|
||||
default:
|
||||
return AccessPublic
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates a ContextNode for consistency and completeness
|
||||
func (cn *ContextNode) Validate() error {
|
||||
if cn.Path == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext, "context path cannot be empty")
|
||||
}
|
||||
|
||||
if err := cn.UCXLAddress.Validate(); err != nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidAddress,
|
||||
"invalid UCXL address").WithUnderlying(err).WithAddress(cn.UCXLAddress)
|
||||
}
|
||||
|
||||
if cn.Summary == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"context summary cannot be empty").WithAddress(cn.UCXLAddress)
|
||||
}
|
||||
|
||||
if cn.RAGConfidence < 0 || cn.RAGConfidence > 1 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"RAG confidence must be between 0 and 1").WithAddress(cn.UCXLAddress).
|
||||
WithContext("confidence", fmt.Sprintf("%.2f", cn.RAGConfidence))
|
||||
}
|
||||
|
||||
if cn.ContextSpecificity < 0 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"context specificity cannot be negative").WithAddress(cn.UCXLAddress).
|
||||
WithContext("specificity", fmt.Sprintf("%d", cn.ContextSpecificity))
|
||||
}
|
||||
|
||||
// Validate role access levels
|
||||
for _, role := range cn.EncryptedFor {
|
||||
if role == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidRole,
|
||||
"encrypted_for roles cannot be empty").WithAddress(cn.UCXLAddress)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate validates a ResolvedContext for consistency and completeness
|
||||
func (rc *ResolvedContext) Validate() error {
|
||||
if err := rc.UCXLAddress.Validate(); err != nil {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidAddress,
|
||||
"invalid UCXL address in resolved context").WithUnderlying(err).WithAddress(rc.UCXLAddress)
|
||||
}
|
||||
|
||||
if rc.Summary == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"resolved context summary cannot be empty").WithAddress(rc.UCXLAddress)
|
||||
}
|
||||
|
||||
if rc.ResolutionConfidence < 0 || rc.ResolutionConfidence > 1 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"resolution confidence must be between 0 and 1").WithAddress(rc.UCXLAddress).
|
||||
WithContext("confidence", fmt.Sprintf("%.2f", rc.ResolutionConfidence))
|
||||
}
|
||||
|
||||
if rc.BoundedDepth < 0 {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"bounded depth cannot be negative").WithAddress(rc.UCXLAddress).
|
||||
WithContext("depth", fmt.Sprintf("%d", rc.BoundedDepth))
|
||||
}
|
||||
|
||||
if rc.ContextSourcePath == "" {
|
||||
return NewContextError(ErrorTypeValidation, ErrorCodeInvalidContext,
|
||||
"context source path cannot be empty").WithAddress(rc.UCXLAddress)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasRole checks if the context node is encrypted for a specific role
|
||||
func (cn *ContextNode) HasRole(role string) bool {
|
||||
for _, r := range cn.EncryptedFor {
|
||||
if r == role || r == "*" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CanAccess checks if a role can access this context based on authority level
|
||||
func (cn *ContextNode) CanAccess(role string, authority config.AuthorityLevel) bool {
|
||||
// Master authority can access everything
|
||||
if authority == config.AuthorityMaster {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if role is explicitly allowed
|
||||
if cn.HasRole(role) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check access level compatibility
|
||||
requiredLevel := AuthorityToAccessLevel(authority)
|
||||
return requiredLevel >= cn.AccessLevel
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of the ContextNode
|
||||
func (cn *ContextNode) Clone() *ContextNode {
|
||||
cloned := &ContextNode{
|
||||
Path: cn.Path,
|
||||
UCXLAddress: *cn.UCXLAddress.Clone(),
|
||||
Summary: cn.Summary,
|
||||
Purpose: cn.Purpose,
|
||||
Technologies: make([]string, len(cn.Technologies)),
|
||||
Tags: make([]string, len(cn.Tags)),
|
||||
Insights: make([]string, len(cn.Insights)),
|
||||
OverridesParent: cn.OverridesParent,
|
||||
ContextSpecificity: cn.ContextSpecificity,
|
||||
AppliesToChildren: cn.AppliesToChildren,
|
||||
GeneratedAt: cn.GeneratedAt,
|
||||
RAGConfidence: cn.RAGConfidence,
|
||||
EncryptedFor: make([]string, len(cn.EncryptedFor)),
|
||||
AccessLevel: cn.AccessLevel,
|
||||
Metadata: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
copy(cloned.Technologies, cn.Technologies)
|
||||
copy(cloned.Tags, cn.Tags)
|
||||
copy(cloned.Insights, cn.Insights)
|
||||
copy(cloned.EncryptedFor, cn.EncryptedFor)
|
||||
|
||||
for k, v := range cn.Metadata {
|
||||
cloned.Metadata[k] = v
|
||||
}
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of the ResolvedContext
|
||||
func (rc *ResolvedContext) Clone() *ResolvedContext {
|
||||
cloned := &ResolvedContext{
|
||||
UCXLAddress: *rc.UCXLAddress.Clone(),
|
||||
Summary: rc.Summary,
|
||||
Purpose: rc.Purpose,
|
||||
Technologies: make([]string, len(rc.Technologies)),
|
||||
Tags: make([]string, len(rc.Tags)),
|
||||
Insights: make([]string, len(rc.Insights)),
|
||||
ContextSourcePath: rc.ContextSourcePath,
|
||||
InheritanceChain: make([]string, len(rc.InheritanceChain)),
|
||||
ResolutionConfidence: rc.ResolutionConfidence,
|
||||
BoundedDepth: rc.BoundedDepth,
|
||||
GlobalContextsApplied: rc.GlobalContextsApplied,
|
||||
ResolvedAt: rc.ResolvedAt,
|
||||
}
|
||||
|
||||
copy(cloned.Technologies, rc.Technologies)
|
||||
copy(cloned.Tags, rc.Tags)
|
||||
copy(cloned.Insights, rc.Insights)
|
||||
copy(cloned.InheritanceChain, rc.InheritanceChain)
|
||||
|
||||
return cloned
|
||||
}
|
||||
Reference in New Issue
Block a user