Comprehensive documentation for coordination, messaging, discovery, and internal systems. Core Coordination Packages: - pkg/election - Democratic leader election (uptime-based, heartbeat mechanism, SLURP integration) - pkg/coordination - Meta-coordination with dependency detection (4 built-in rules) - coordinator/ - Task orchestration and assignment (AI-powered scoring) - discovery/ - mDNS peer discovery (automatic LAN detection) Messaging & P2P Infrastructure: - pubsub/ - GossipSub messaging (31 message types, role-based topics, HMMM integration) - p2p/ - libp2p networking (DHT modes, connection management, security) Monitoring & Health: - pkg/metrics - Prometheus metrics (80+ metrics across 12 categories) - pkg/health - Health monitoring (4 HTTP endpoints, enhanced checks, graceful degradation) Internal Systems: - internal/licensing - License validation (KACHING integration, cluster leases, fail-closed) - internal/hapui - Human Agent Portal UI (9 commands, HMMM wizard, UCXL browser, decision voting) - internal/backbeat - P2P operation telemetry (6 phases, beat synchronization, health reporting) Documentation Statistics (Phase 3): - 10 packages documented (~18,000 lines) - 31 PubSub message types cataloged - 80+ Prometheus metrics documented - Complete API references with examples - Integration patterns and best practices Key Features Documented: - Election: 5 triggers, candidate scoring (5 weighted components), stability windows - Coordination: AI-powered dependency detection, cross-repo sessions, escalation handling - PubSub: Topic patterns, message envelopes, SHHH redaction, Hypercore logging - Metrics: All metric types with labels, Prometheus scrape config, alert rules - Health: Liveness vs readiness, critical checks, Kubernetes integration - Licensing: Grace periods, circuit breaker, cluster lease management - HAP UI: Interactive terminal commands, HMMM composition wizard, web interface (beta) - BACKBEAT: 6-phase operation tracking, beat budget estimation, drift detection Implementation Status Marked: - ✅ Production: Election, metrics, health, licensing, pubsub, p2p, discovery, coordinator - 🔶 Beta: HAP web interface, BACKBEAT telemetry, advanced coordination - 🔷 Alpha: SLURP election scoring - ⚠️ Experimental: Meta-coordination, AI-powered dependency detection Progress: 22/62 files complete (35%) Next Phase: AI providers, SLURP system, API layer, reasoning engine 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1060 lines
30 KiB
Markdown
1060 lines
30 KiB
Markdown
# PubSub Package
|
|
|
|
## Overview
|
|
|
|
The `pubsub` package provides a libp2p GossipSub-based publish/subscribe messaging infrastructure for CHORUS. It enables distributed coordination through multiple topic types, supporting task coordination (Bzzz), meta-discussion (HMMM), context feedback (RL learning), and role-based collaboration across the autonomous agent network.
|
|
|
|
**Package Path:** `/home/tony/chorus/project-queues/active/CHORUS/pubsub/`
|
|
|
|
**Key Features:**
|
|
- Three static topics (Bzzz coordination, HMMM meta-discussion, Context feedback)
|
|
- Dynamic per-task, per-issue, and per-project topic management
|
|
- Role-based topic routing (roles, expertise, reporting hierarchy)
|
|
- 31+ message types for different coordination scenarios
|
|
- SHHH redaction integration for sensitive data
|
|
- Hypercore logging integration for event persistence
|
|
- Raw message publication for custom schemas
|
|
- HMMM adapter for per-issue room communication
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
```
|
|
PubSub
|
|
├── Static Topics
|
|
│ ├── chorusTopic - "CHORUS/coordination/v1" (Bzzz task coordination)
|
|
│ ├── hmmmTopic - "hmmm/meta-discussion/v1" (HMMM meta-discussion)
|
|
│ └── contextTopic - "CHORUS/context-feedback/v1" (RL context feedback)
|
|
├── Dynamic Topics
|
|
│ ├── dynamicTopics - map[string]*pubsub.Topic
|
|
│ ├── dynamicSubs - map[string]*pubsub.Subscription
|
|
│ └── dynamicHandlers - map[string]func([]byte, peer.ID)
|
|
├── Message Handlers
|
|
│ ├── HmmmMessageHandler - External HMMM handler
|
|
│ └── ContextFeedbackHandler - External context handler
|
|
├── Integration
|
|
│ ├── hypercoreLog - HypercoreLogger for event persistence
|
|
│ └── redactor - *shhh.Sentinel for message sanitization
|
|
└── Adapters
|
|
└── GossipPublisher - HMMM adapter for per-issue topics
|
|
```
|
|
|
|
## Message Types
|
|
|
|
### Bzzz Coordination Messages (6 types)
|
|
|
|
Task coordination and agent availability messages published to `CHORUS/coordination/v1`:
|
|
|
|
| Message Type | Purpose | Usage |
|
|
|--------------|---------|-------|
|
|
| `TaskAnnouncement` | New task available for claiming | Broadcast when task created |
|
|
| `TaskClaim` | Agent claims a task | Response to TaskAnnouncement |
|
|
| `TaskProgress` | Task progress update | Periodic updates during execution |
|
|
| `TaskComplete` | Task completed successfully | Final status notification |
|
|
| `CapabilityBcast` | Agent capability announcement | Broadcast when capabilities change |
|
|
| `AvailabilityBcast` | Agent availability status | Regular heartbeat (30s intervals) |
|
|
|
|
### HMMM Meta-Discussion Messages (7 types)
|
|
|
|
Agent-to-agent meta-discussion published to `hmmm/meta-discussion/v1`:
|
|
|
|
| Message Type | Purpose | Usage |
|
|
|--------------|---------|-------|
|
|
| `MetaDiscussion` | Generic discussion message | General coordination discussion |
|
|
| `TaskHelpRequest` | Request assistance from peers | When agent needs help |
|
|
| `TaskHelpResponse` | Response to help request | Offer assistance |
|
|
| `CoordinationRequest` | Request coordination session | Multi-agent coordination |
|
|
| `CoordinationComplete` | Coordination session finished | Session completion |
|
|
| `DependencyAlert` | Dependency detected | Alert about task dependencies |
|
|
| `EscalationTrigger` | Human escalation needed | Critical issues requiring human |
|
|
|
|
### Role-Based Collaboration Messages (10 types)
|
|
|
|
Role-based collaboration published to `hmmm/meta-discussion/v1`:
|
|
|
|
| Message Type | Purpose | Usage |
|
|
|--------------|---------|-------|
|
|
| `RoleAnnouncement` | Agent announces role/capabilities | Agent startup |
|
|
| `ExpertiseRequest` | Request specific expertise | Need domain knowledge |
|
|
| `ExpertiseResponse` | Offer expertise | Response to request |
|
|
| `StatusUpdate` | Regular status updates | Periodic role status |
|
|
| `WorkAllocation` | Allocate work to roles | Task distribution |
|
|
| `RoleCollaboration` | Cross-role collaboration | Multi-role coordination |
|
|
| `MentorshipRequest` | Junior seeks mentorship | Learning assistance |
|
|
| `MentorshipResponse` | Senior provides mentorship | Teaching response |
|
|
| `ProjectUpdate` | Project-level status | Project progress |
|
|
| `DeliverableReady` | Deliverable complete | Work product ready |
|
|
|
|
### Context Feedback Messages (5 types)
|
|
|
|
RL Context Curator feedback published to `CHORUS/context-feedback/v1`:
|
|
|
|
| Message Type | Purpose | Usage |
|
|
|--------------|---------|-------|
|
|
| `FeedbackEvent` | Context feedback for RL | Reinforcement learning signals |
|
|
| `ContextRequest` | Request context from HCFS | Query context system |
|
|
| `ContextResponse` | Context data response | HCFS response |
|
|
| `ContextUsage` | Context usage patterns | Usage metrics |
|
|
| `ContextRelevance` | Context relevance scoring | Relevance feedback |
|
|
|
|
### SLURP Event Integration Messages (3 types)
|
|
|
|
HMMM-SLURP integration published to `hmmm/meta-discussion/v1`:
|
|
|
|
| Message Type | Purpose | Usage |
|
|
|--------------|---------|-------|
|
|
| `SlurpEventGenerated` | HMMM consensus generated event | SLURP event creation |
|
|
| `SlurpEventAck` | Acknowledge SLURP event | Receipt confirmation |
|
|
| `SlurpContextUpdate` | Context update from SLURP | SLURP context sync |
|
|
|
|
## Topic Naming Conventions
|
|
|
|
### Static Topics
|
|
|
|
```
|
|
CHORUS/coordination/v1 - Bzzz task coordination
|
|
hmmm/meta-discussion/v1 - HMMM meta-discussion
|
|
CHORUS/context-feedback/v1 - Context feedback (RL)
|
|
```
|
|
|
|
### Dynamic Topic Patterns
|
|
|
|
```
|
|
CHORUS/roles/<role>/v1 - Role-specific (e.g., "developer", "architect")
|
|
CHORUS/expertise/<expertise>/v1 - Expertise-specific (e.g., "golang", "kubernetes")
|
|
CHORUS/hierarchy/<supervisor>/v1 - Reporting hierarchy
|
|
CHORUS/projects/<project_id>/coordination/v1 - Project-specific
|
|
CHORUS/meta/issue/<issue_id> - Per-issue HMMM rooms (custom schema)
|
|
<custom_topic> - Any custom topic for specialized needs
|
|
```
|
|
|
|
### Topic Naming Rules
|
|
|
|
1. Use lowercase with underscores for multi-word identifiers
|
|
2. Version suffix `/v1` for future compatibility
|
|
3. Prefix with `CHORUS/` for CHORUS-specific topics
|
|
4. Prefix with `hmmm/` for HMMM-specific topics
|
|
5. Use hierarchical structure for discoverability
|
|
|
|
## Message Format
|
|
|
|
### Standard CHORUS Message Envelope
|
|
|
|
```go
|
|
type Message struct {
|
|
Type MessageType `json:"type"` // Message type constant
|
|
From string `json:"from"` // Peer ID of sender
|
|
Timestamp time.Time `json:"timestamp"` // Message timestamp
|
|
Data map[string]interface{} `json:"data"` // Message payload
|
|
HopCount int `json:"hop_count,omitempty"` // Antennae hop limiting
|
|
|
|
// Role-based collaboration fields
|
|
FromRole string `json:"from_role,omitempty"` // Role of sender
|
|
ToRoles []string `json:"to_roles,omitempty"` // Target roles
|
|
RequiredExpertise []string `json:"required_expertise,omitempty"` // Required expertise
|
|
ProjectID string `json:"project_id,omitempty"` // Associated project
|
|
Priority string `json:"priority,omitempty"` // low, medium, high, urgent
|
|
ThreadID string `json:"thread_id,omitempty"` // Conversation thread
|
|
}
|
|
```
|
|
|
|
### Message Publishing
|
|
|
|
Messages are automatically wrapped in the standard envelope when using:
|
|
- `PublishBzzzMessage()`
|
|
- `PublishHmmmMessage()`
|
|
- `PublishContextFeedbackMessage()`
|
|
- `PublishToDynamicTopic()`
|
|
- `PublishRoleBasedMessage()`
|
|
|
|
For custom schemas (e.g., HMMM per-issue rooms), use `PublishRaw()` to bypass the envelope.
|
|
|
|
## GossipSub Configuration
|
|
|
|
### Validation and Security
|
|
|
|
```go
|
|
pubsub.NewGossipSub(ctx, h,
|
|
pubsub.WithMessageSigning(true), // Sign all messages
|
|
pubsub.WithStrictSignatureVerification(true), // Verify signatures
|
|
pubsub.WithValidateQueueSize(256), // Validation queue size
|
|
pubsub.WithValidateThrottle(1024), // Validation throughput
|
|
)
|
|
```
|
|
|
|
### Security Features
|
|
|
|
- **Message Signing:** All messages cryptographically signed by sender
|
|
- **Signature Verification:** Strict verification prevents impersonation
|
|
- **SHHH Redaction:** Automatic sanitization of sensitive data before publication
|
|
- **Validation Queue:** 256 messages buffered for validation
|
|
- **Validation Throttle:** Process up to 1024 validations concurrently
|
|
|
|
### Network Properties
|
|
|
|
- **Protocol:** libp2p GossipSub (epidemic broadcast)
|
|
- **Delivery:** Best-effort, eventually consistent
|
|
- **Ordering:** No guaranteed message ordering
|
|
- **Reliability:** At-most-once delivery (use ACK patterns for reliability)
|
|
|
|
## API Reference
|
|
|
|
### Initialization
|
|
|
|
#### NewPubSub
|
|
|
|
```go
|
|
func NewPubSub(ctx context.Context, h host.Host, chorusTopic, hmmmTopic string) (*PubSub, error)
|
|
```
|
|
|
|
Creates a new PubSub instance with static topics.
|
|
|
|
**Parameters:**
|
|
- `ctx` - Context for lifecycle management
|
|
- `h` - libp2p Host instance
|
|
- `chorusTopic` - Bzzz coordination topic (default: "CHORUS/coordination/v1")
|
|
- `hmmmTopic` - HMMM meta-discussion topic (default: "hmmm/meta-discussion/v1")
|
|
|
|
**Returns:** PubSub instance or error
|
|
|
|
**Example:**
|
|
```go
|
|
ps, err := pubsub.NewPubSub(ctx, node.Host(), "CHORUS/coordination/v1", "hmmm/meta-discussion/v1")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer ps.Close()
|
|
```
|
|
|
|
#### NewPubSubWithLogger
|
|
|
|
```go
|
|
func NewPubSubWithLogger(ctx context.Context, h host.Host, chorusTopic, hmmmTopic string,
|
|
logger HypercoreLogger) (*PubSub, error)
|
|
```
|
|
|
|
Creates PubSub with hypercore logging integration.
|
|
|
|
**Parameters:**
|
|
- Same as NewPubSub, plus:
|
|
- `logger` - HypercoreLogger implementation for event persistence
|
|
|
|
**Example:**
|
|
```go
|
|
ps, err := pubsub.NewPubSubWithLogger(ctx, node.Host(),
|
|
"chorus/coordination/v1", "hmmm/meta-discussion/v1", hlog)
|
|
```
|
|
|
|
### Static Topic Publishing
|
|
|
|
#### PublishBzzzMessage
|
|
|
|
```go
|
|
func (p *PubSub) PublishBzzzMessage(msgType MessageType, data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes to Bzzz coordination topic (`CHORUS/coordination/v1`).
|
|
|
|
**Parameters:**
|
|
- `msgType` - One of: TaskAnnouncement, TaskClaim, TaskProgress, TaskComplete, CapabilityBcast, AvailabilityBcast
|
|
- `data` - Message payload (automatically redacted if SHHH configured)
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishBzzzMessage(pubsub.TaskAnnouncement, map[string]interface{}{
|
|
"task_id": "task-123",
|
|
"description": "Deploy service to production",
|
|
"capabilities": []string{"deployment", "kubernetes"},
|
|
})
|
|
```
|
|
|
|
#### PublishHmmmMessage
|
|
|
|
```go
|
|
func (p *PubSub) PublishHmmmMessage(msgType MessageType, data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes to HMMM meta-discussion topic (`hmmm/meta-discussion/v1`).
|
|
|
|
**Parameters:**
|
|
- `msgType` - One of: MetaDiscussion, TaskHelpRequest, TaskHelpResponse, CoordinationRequest, etc.
|
|
- `data` - Message payload
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishHmmmMessage(pubsub.TaskHelpRequest, map[string]interface{}{
|
|
"task_id": "task-456",
|
|
"help_needed": "Need expertise in Go concurrency patterns",
|
|
"urgency": "medium",
|
|
})
|
|
```
|
|
|
|
#### PublishContextFeedbackMessage
|
|
|
|
```go
|
|
func (p *PubSub) PublishContextFeedbackMessage(msgType MessageType, data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes to Context feedback topic (`CHORUS/context-feedback/v1`).
|
|
|
|
**Parameters:**
|
|
- `msgType` - One of: FeedbackEvent, ContextRequest, ContextResponse, ContextUsage, ContextRelevance
|
|
- `data` - Feedback payload
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishContextFeedbackMessage(pubsub.FeedbackEvent, map[string]interface{}{
|
|
"context_path": "/project/docs/api.md",
|
|
"relevance_score": 0.95,
|
|
"usage_count": 12,
|
|
})
|
|
```
|
|
|
|
### Dynamic Topic Management
|
|
|
|
#### JoinDynamicTopic
|
|
|
|
```go
|
|
func (p *PubSub) JoinDynamicTopic(topicName string) error
|
|
```
|
|
|
|
Joins a dynamic topic and subscribes to messages.
|
|
|
|
**Parameters:**
|
|
- `topicName` - Topic to join (idempotent)
|
|
|
|
**Returns:** error if join fails
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.JoinDynamicTopic("CHORUS/projects/my-project/coordination/v1")
|
|
```
|
|
|
|
#### LeaveDynamicTopic
|
|
|
|
```go
|
|
func (p *PubSub) LeaveDynamicTopic(topicName string)
|
|
```
|
|
|
|
Leaves a dynamic topic and cancels subscription.
|
|
|
|
**Parameters:**
|
|
- `topicName` - Topic to leave
|
|
|
|
**Example:**
|
|
```go
|
|
ps.LeaveDynamicTopic("CHORUS/projects/my-project/coordination/v1")
|
|
```
|
|
|
|
#### PublishToDynamicTopic
|
|
|
|
```go
|
|
func (p *PubSub) PublishToDynamicTopic(topicName string, msgType MessageType,
|
|
data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes message to a dynamic topic (must be joined first).
|
|
|
|
**Parameters:**
|
|
- `topicName` - Target topic (must be joined)
|
|
- `msgType` - Message type
|
|
- `data` - Message payload
|
|
|
|
**Returns:** error if not subscribed or publish fails
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishToDynamicTopic("CHORUS/projects/my-project/coordination/v1",
|
|
pubsub.StatusUpdate, map[string]interface{}{
|
|
"status": "in_progress",
|
|
"completion": 0.45,
|
|
})
|
|
```
|
|
|
|
### Role-Based Topics
|
|
|
|
#### JoinRoleBasedTopics
|
|
|
|
```go
|
|
func (p *PubSub) JoinRoleBasedTopics(role string, expertise []string, reportsTo []string) error
|
|
```
|
|
|
|
Joins topics based on role configuration.
|
|
|
|
**Parameters:**
|
|
- `role` - Agent role (e.g., "Developer", "Architect")
|
|
- `expertise` - Expertise areas (e.g., ["golang", "kubernetes"])
|
|
- `reportsTo` - Reporting hierarchy (supervisor roles)
|
|
|
|
**Topics Joined:**
|
|
- `CHORUS/roles/<role>/v1`
|
|
- `CHORUS/expertise/<expertise>/v1` (for each expertise)
|
|
- `CHORUS/hierarchy/<supervisor>/v1` (for each supervisor)
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.JoinRoleBasedTopics(
|
|
"Senior Developer",
|
|
[]string{"golang", "distributed_systems", "kubernetes"},
|
|
[]string{"Tech Lead", "Engineering Manager"},
|
|
)
|
|
```
|
|
|
|
#### PublishRoleBasedMessage
|
|
|
|
```go
|
|
func (p *PubSub) PublishRoleBasedMessage(msgType MessageType, data map[string]interface{},
|
|
opts MessageOptions) error
|
|
```
|
|
|
|
Publishes role-based collaboration message with routing metadata.
|
|
|
|
**Parameters:**
|
|
- `msgType` - One of the role-based message types
|
|
- `data` - Message payload
|
|
- `opts` - MessageOptions with routing metadata
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishRoleBasedMessage(pubsub.ExpertiseRequest,
|
|
map[string]interface{}{
|
|
"question": "How to handle distributed transactions?",
|
|
"context": "Microservices architecture",
|
|
},
|
|
pubsub.MessageOptions{
|
|
FromRole: "Junior Developer",
|
|
ToRoles: []string{"Senior Developer", "Architect"},
|
|
RequiredExpertise: []string{"distributed_systems", "golang"},
|
|
ProjectID: "project-789",
|
|
Priority: "high",
|
|
ThreadID: "thread-abc",
|
|
})
|
|
```
|
|
|
|
### Project Topics
|
|
|
|
#### JoinProjectTopic
|
|
|
|
```go
|
|
func (p *PubSub) JoinProjectTopic(projectID string) error
|
|
```
|
|
|
|
Joins project-specific coordination topic.
|
|
|
|
**Parameters:**
|
|
- `projectID` - Project identifier
|
|
|
|
**Topic:** `CHORUS/projects/<project_id>/coordination/v1`
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.JoinProjectTopic("chorus-deployment-2025")
|
|
```
|
|
|
|
### Raw Message Publication
|
|
|
|
#### PublishRaw
|
|
|
|
```go
|
|
func (p *PubSub) PublishRaw(topicName string, payload []byte) error
|
|
```
|
|
|
|
Publishes raw JSON payload without CHORUS message envelope. Used for custom schemas (e.g., HMMM per-issue rooms).
|
|
|
|
**Parameters:**
|
|
- `topicName` - Target topic (static or dynamic)
|
|
- `payload` - Raw JSON bytes
|
|
|
|
**Returns:** error if not subscribed
|
|
|
|
**Example:**
|
|
```go
|
|
// Custom HMMM message format
|
|
hmmmMsg := map[string]interface{}{
|
|
"type": "issue_discussion",
|
|
"issue_id": 42,
|
|
"message": "Need review on API design",
|
|
}
|
|
payload, _ := json.Marshal(hmmmMsg)
|
|
err := ps.PublishRaw("CHORUS/meta/issue/42", payload)
|
|
```
|
|
|
|
#### SubscribeRawTopic
|
|
|
|
```go
|
|
func (p *PubSub) SubscribeRawTopic(topicName string, handler func([]byte, peer.ID)) error
|
|
```
|
|
|
|
Subscribes to topic with raw message handler (bypasses CHORUS envelope parsing).
|
|
|
|
**Parameters:**
|
|
- `topicName` - Topic to subscribe
|
|
- `handler` - Function receiving raw payload and sender peer ID
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.SubscribeRawTopic("CHORUS/meta/issue/42", func(payload []byte, from peer.ID) {
|
|
var msg map[string]interface{}
|
|
json.Unmarshal(payload, &msg)
|
|
fmt.Printf("Raw message from %s: %v\n", from.ShortString(), msg)
|
|
})
|
|
```
|
|
|
|
### SLURP Integration
|
|
|
|
#### PublishSlurpEventGenerated
|
|
|
|
```go
|
|
func (p *PubSub) PublishSlurpEventGenerated(data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes SLURP event generation notification.
|
|
|
|
**Example:**
|
|
```go
|
|
err := ps.PublishSlurpEventGenerated(map[string]interface{}{
|
|
"event_id": "evt-123",
|
|
"event_type": "deployment",
|
|
"discussion_id": "disc-456",
|
|
"consensus": true,
|
|
})
|
|
```
|
|
|
|
#### PublishSlurpEventAck
|
|
|
|
```go
|
|
func (p *PubSub) PublishSlurpEventAck(data map[string]interface{}) error
|
|
```
|
|
|
|
Acknowledges receipt of SLURP event.
|
|
|
|
#### PublishSlurpContextUpdate
|
|
|
|
```go
|
|
func (p *PubSub) PublishSlurpContextUpdate(data map[string]interface{}) error
|
|
```
|
|
|
|
Publishes context update from SLURP system.
|
|
|
|
### Message Handler Configuration
|
|
|
|
#### SetHmmmMessageHandler
|
|
|
|
```go
|
|
func (p *PubSub) SetHmmmMessageHandler(handler func(msg Message, from peer.ID))
|
|
```
|
|
|
|
Sets external handler for HMMM messages. Overrides default logging-only handler.
|
|
|
|
**Parameters:**
|
|
- `handler` - Function receiving parsed Message and sender peer ID
|
|
|
|
**Example:**
|
|
```go
|
|
ps.SetHmmmMessageHandler(func(msg Message, from peer.ID) {
|
|
fmt.Printf("HMMM [%s] from %s: %v\n", msg.Type, from.ShortString(), msg.Data)
|
|
// Custom processing logic
|
|
})
|
|
```
|
|
|
|
#### SetContextFeedbackHandler
|
|
|
|
```go
|
|
func (p *PubSub) SetContextFeedbackHandler(handler func(msg Message, from peer.ID))
|
|
```
|
|
|
|
Sets external handler for context feedback messages.
|
|
|
|
**Example:**
|
|
```go
|
|
ps.SetContextFeedbackHandler(func(msg Message, from peer.ID) {
|
|
if msg.Type == pubsub.FeedbackEvent {
|
|
// Process RL feedback
|
|
}
|
|
})
|
|
```
|
|
|
|
### Integration
|
|
|
|
#### SetRedactor
|
|
|
|
```go
|
|
func (p *PubSub) SetRedactor(redactor *shhh.Sentinel)
|
|
```
|
|
|
|
Wires SHHH sentinel for automatic message sanitization before publication.
|
|
|
|
**Parameters:**
|
|
- `redactor` - SHHH Sentinel instance
|
|
|
|
**Example:**
|
|
```go
|
|
sentinel := shhh.NewSentinel(ctx, config)
|
|
ps.SetRedactor(sentinel)
|
|
// All subsequent publications automatically redacted
|
|
```
|
|
|
|
#### GetHypercoreLog
|
|
|
|
```go
|
|
func (p *PubSub) GetHypercoreLog() HypercoreLogger
|
|
```
|
|
|
|
Returns configured hypercore logger for external access.
|
|
|
|
**Returns:** HypercoreLogger instance or nil
|
|
|
|
### Lifecycle
|
|
|
|
#### Close
|
|
|
|
```go
|
|
func (p *PubSub) Close() error
|
|
```
|
|
|
|
Shuts down PubSub, cancels all subscriptions, and closes all topics.
|
|
|
|
**Example:**
|
|
```go
|
|
defer ps.Close()
|
|
```
|
|
|
|
## HMMM Adapter
|
|
|
|
### GossipPublisher
|
|
|
|
The `GossipPublisher` adapter bridges HMMM's per-issue room system with CHORUS pubsub.
|
|
|
|
#### NewGossipPublisher
|
|
|
|
```go
|
|
func NewGossipPublisher(ps *PubSub) *GossipPublisher
|
|
```
|
|
|
|
Creates HMMM adapter wrapping PubSub instance.
|
|
|
|
**Parameters:**
|
|
- `ps` - PubSub instance
|
|
|
|
**Returns:** GossipPublisher adapter
|
|
|
|
#### Publish
|
|
|
|
```go
|
|
func (g *GossipPublisher) Publish(ctx context.Context, topic string, payload []byte) error
|
|
```
|
|
|
|
Ensures agent is subscribed to per-issue topic and publishes raw payload.
|
|
|
|
**Parameters:**
|
|
- `ctx` - Context
|
|
- `topic` - Per-issue topic (e.g., "CHORUS/meta/issue/42")
|
|
- `payload` - Raw JSON message (HMMM schema)
|
|
|
|
**Behavior:**
|
|
1. Joins dynamic topic (idempotent)
|
|
2. Publishes raw payload (bypasses CHORUS envelope)
|
|
|
|
**Example:**
|
|
```go
|
|
adapter := pubsub.NewGossipPublisher(ps)
|
|
err := adapter.Publish(ctx, "CHORUS/meta/issue/42", hmmmPayload)
|
|
```
|
|
|
|
## Subscription Patterns
|
|
|
|
### Static Topic Subscription
|
|
|
|
Static topics are automatically subscribed during `NewPubSub()`:
|
|
- `CHORUS/coordination/v1` - Bzzz messages
|
|
- `hmmm/meta-discussion/v1` - HMMM messages
|
|
- `CHORUS/context-feedback/v1` - Context feedback
|
|
|
|
Messages handled by:
|
|
- `handleBzzzMessages()` - Processes Bzzz coordination
|
|
- `handleHmmmMessages()` - Processes HMMM (delegates to external handler if set)
|
|
- `handleContextFeedbackMessages()` - Processes context feedback
|
|
|
|
### Dynamic Topic Subscription
|
|
|
|
Dynamic topics require explicit join:
|
|
|
|
```go
|
|
// Task-specific topic
|
|
ps.JoinDynamicTopic("CHORUS/tasks/task-123/v1")
|
|
|
|
// Project-specific topic
|
|
ps.JoinProjectTopic("project-456")
|
|
|
|
// Role-based topics
|
|
ps.JoinRoleBasedTopics("Developer", []string{"golang"}, []string{"Tech Lead"})
|
|
|
|
// Custom raw handler
|
|
ps.SubscribeRawTopic("CHORUS/meta/issue/789", func(payload []byte, from peer.ID) {
|
|
// Custom processing
|
|
})
|
|
```
|
|
|
|
### Message Filtering
|
|
|
|
Agents automatically filter out their own messages:
|
|
|
|
```go
|
|
if msg.ReceivedFrom == p.host.ID() {
|
|
continue // Ignore own messages
|
|
}
|
|
```
|
|
|
|
### Role-Based Routing
|
|
|
|
Messages with role metadata are automatically routed to appropriate handlers:
|
|
|
|
```go
|
|
if msg.FromRole != "" && len(msg.ToRoles) > 0 {
|
|
// Check if this agent's role matches target roles
|
|
if containsRole(myRole, msg.ToRoles) {
|
|
// Process message
|
|
}
|
|
}
|
|
```
|
|
|
|
## Hypercore Logging Integration
|
|
|
|
### Log Mapping
|
|
|
|
PubSub messages are automatically logged to Hypercore with appropriate log types:
|
|
|
|
| Message Type | Hypercore Log Type | Topic |
|
|
|--------------|-------------------|-------|
|
|
| TaskAnnouncement | task_announced | CHORUS |
|
|
| TaskClaim | task_claimed | CHORUS |
|
|
| TaskProgress | task_progress | CHORUS |
|
|
| TaskComplete | task_completed | CHORUS |
|
|
| CapabilityBcast | capability_broadcast | CHORUS |
|
|
| AvailabilityBcast | network_event | CHORUS |
|
|
| MetaDiscussion | collaboration | hmmm |
|
|
| TaskHelpRequest | collaboration | hmmm |
|
|
| EscalationTrigger | escalation | hmmm |
|
|
| Role messages | collaboration | hmmm |
|
|
| FeedbackEvent | context_feedback | context_feedback |
|
|
| ContextRequest | context_request | context_feedback |
|
|
|
|
### Log Data Format
|
|
|
|
```go
|
|
logData := map[string]interface{}{
|
|
"message_type": string(msg.Type),
|
|
"from_peer": from.String(),
|
|
"from_short": from.ShortString(),
|
|
"timestamp": msg.Timestamp,
|
|
"data": msg.Data,
|
|
"topic": "CHORUS",
|
|
"from_role": msg.FromRole,
|
|
"to_roles": msg.ToRoles,
|
|
"required_expertise": msg.RequiredExpertise,
|
|
"project_id": msg.ProjectID,
|
|
"priority": msg.Priority,
|
|
"thread_id": msg.ThreadID,
|
|
}
|
|
```
|
|
|
|
## SHHH Redaction Integration
|
|
|
|
### Automatic Sanitization
|
|
|
|
All outbound messages are sanitized if redactor is configured:
|
|
|
|
```go
|
|
ps.SetRedactor(sentinel)
|
|
```
|
|
|
|
### Redaction Process
|
|
|
|
1. Payload is cloned (deep copy)
|
|
2. Redactor scans for sensitive patterns
|
|
3. Sensitive data is redacted/masked
|
|
4. Sanitized payload is published
|
|
|
|
### Redaction Labels
|
|
|
|
```go
|
|
labels := map[string]string{
|
|
"source": "pubsub",
|
|
"topic": topicName,
|
|
"message_type": string(msgType),
|
|
}
|
|
sentinel.RedactMapWithLabels(ctx, payload, labels)
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Task Coordination
|
|
|
|
```go
|
|
// Initialize PubSub
|
|
ps, err := pubsub.NewPubSub(ctx, node.Host(), "", "")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer ps.Close()
|
|
|
|
// Announce task
|
|
ps.PublishBzzzMessage(pubsub.TaskAnnouncement, map[string]interface{}{
|
|
"task_id": "task-123",
|
|
"description": "Deploy service",
|
|
"capabilities": []string{"deployment"},
|
|
})
|
|
|
|
// Claim task
|
|
ps.PublishBzzzMessage(pubsub.TaskClaim, map[string]interface{}{
|
|
"task_id": "task-123",
|
|
"agent_id": ps.Host().ID().String(),
|
|
})
|
|
|
|
// Report progress
|
|
ps.PublishBzzzMessage(pubsub.TaskProgress, map[string]interface{}{
|
|
"task_id": "task-123",
|
|
"progress": 0.50,
|
|
"status": "deploying",
|
|
})
|
|
|
|
// Mark complete
|
|
ps.PublishBzzzMessage(pubsub.TaskComplete, map[string]interface{}{
|
|
"task_id": "task-123",
|
|
"result": "success",
|
|
"output": "Service deployed to production",
|
|
})
|
|
```
|
|
|
|
### Role-Based Collaboration
|
|
|
|
```go
|
|
// Join role-based topics
|
|
ps.JoinRoleBasedTopics("Senior Developer",
|
|
[]string{"golang", "kubernetes"},
|
|
[]string{"Tech Lead"})
|
|
|
|
// Request expertise
|
|
ps.PublishRoleBasedMessage(pubsub.ExpertiseRequest,
|
|
map[string]interface{}{
|
|
"question": "How to implement distributed tracing?",
|
|
"context": "Microservices deployment",
|
|
},
|
|
pubsub.MessageOptions{
|
|
FromRole: "Junior Developer",
|
|
ToRoles: []string{"Senior Developer", "Architect"},
|
|
RequiredExpertise: []string{"distributed_systems"},
|
|
Priority: "medium",
|
|
})
|
|
|
|
// Respond with expertise
|
|
ps.PublishRoleBasedMessage(pubsub.ExpertiseResponse,
|
|
map[string]interface{}{
|
|
"answer": "Use OpenTelemetry with Jaeger backend",
|
|
"resources": []string{"https://opentelemetry.io/docs"},
|
|
},
|
|
pubsub.MessageOptions{
|
|
FromRole: "Senior Developer",
|
|
ThreadID: "thread-123",
|
|
})
|
|
```
|
|
|
|
### HMMM Per-Issue Rooms
|
|
|
|
```go
|
|
// Create HMMM adapter
|
|
adapter := pubsub.NewGossipPublisher(ps)
|
|
|
|
// Publish to per-issue room
|
|
issueID := 42
|
|
topic := fmt.Sprintf("CHORUS/meta/issue/%d", issueID)
|
|
message := map[string]interface{}{
|
|
"type": "discussion",
|
|
"message": "API design looks good, approved",
|
|
"issue_id": issueID,
|
|
}
|
|
payload, _ := json.Marshal(message)
|
|
adapter.Publish(ctx, topic, payload)
|
|
|
|
// Subscribe with custom handler
|
|
ps.SubscribeRawTopic(topic, func(payload []byte, from peer.ID) {
|
|
var msg map[string]interface{}
|
|
json.Unmarshal(payload, &msg)
|
|
fmt.Printf("Issue #%d message: %s\n", issueID, msg["message"])
|
|
})
|
|
```
|
|
|
|
### Project Coordination
|
|
|
|
```go
|
|
// Join project topic
|
|
projectID := "chorus-deployment-2025"
|
|
ps.JoinProjectTopic(projectID)
|
|
|
|
// Send project update
|
|
ps.PublishToDynamicTopic(
|
|
fmt.Sprintf("CHORUS/projects/%s/coordination/v1", projectID),
|
|
pubsub.ProjectUpdate,
|
|
map[string]interface{}{
|
|
"project_id": projectID,
|
|
"phase": "testing",
|
|
"completion": 0.75,
|
|
"blockers": []string{},
|
|
})
|
|
```
|
|
|
|
### Context Feedback for RL
|
|
|
|
```go
|
|
// Report context usage
|
|
ps.PublishContextFeedbackMessage(pubsub.ContextUsage, map[string]interface{}{
|
|
"context_path": "/project/docs/architecture.md",
|
|
"usage_count": 5,
|
|
"query": "How does the authentication system work?",
|
|
})
|
|
|
|
// Report relevance
|
|
ps.PublishContextFeedbackMessage(pubsub.ContextRelevance, map[string]interface{}{
|
|
"context_path": "/project/docs/architecture.md",
|
|
"relevance_score": 0.92,
|
|
"query": "authentication flow",
|
|
})
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Topic Management
|
|
|
|
1. **Use Static Topics for Global Coordination**
|
|
- Bzzz: Task announcements, claims, completion
|
|
- HMMM: General meta-discussion, help requests
|
|
- Context: RL feedback, context queries
|
|
|
|
2. **Use Dynamic Topics for Scoped Coordination**
|
|
- Project-specific: Per-project coordination
|
|
- Task-specific: Multi-agent task coordination
|
|
- Issue-specific: HMMM per-issue rooms
|
|
|
|
3. **Use Role Topics for Targeted Messages**
|
|
- Expertise requests to specific roles
|
|
- Hierarchical escalation
|
|
- Skill-based routing
|
|
|
|
### Message Design
|
|
|
|
1. **Include Sufficient Context**
|
|
- Always include identifiers (task_id, project_id, etc.)
|
|
- Timestamp messages appropriately
|
|
- Use thread_id for conversation threading
|
|
|
|
2. **Use Appropriate Priority**
|
|
- `urgent`: Immediate attention required
|
|
- `high`: Important, handle soon
|
|
- `medium`: Normal priority
|
|
- `low`: Background, handle when available
|
|
|
|
3. **Design for Idempotency**
|
|
- Assume messages may be received multiple times
|
|
- Use unique identifiers for deduplication
|
|
- Design state transitions to be idempotent
|
|
|
|
### Performance
|
|
|
|
1. **Topic Cleanup**
|
|
- Leave dynamic topics when no longer needed
|
|
- Prevents memory leaks and wasted bandwidth
|
|
|
|
2. **Message Size**
|
|
- Keep payloads compact
|
|
- Avoid large binary data in messages
|
|
- Use content-addressed storage for large data
|
|
|
|
3. **Rate Limiting**
|
|
- Don't spam availability broadcasts (30s intervals)
|
|
- Batch related messages when possible
|
|
- Use project topics to reduce global traffic
|
|
|
|
### Security
|
|
|
|
1. **Always Configure SHHH**
|
|
- Set redactor before publishing sensitive data
|
|
- Use labels for audit trails
|
|
- Validate redaction in tests
|
|
|
|
2. **Validate Message Sources**
|
|
- Check peer identity for sensitive operations
|
|
- Use thread_id for conversation integrity
|
|
- Implement ACLs for privileged operations
|
|
|
|
3. **Never Trust Message Content**
|
|
- Validate all inputs
|
|
- Sanitize data before persistence
|
|
- Implement rate limiting per peer
|
|
|
|
## Testing
|
|
|
|
### Unit Tests
|
|
|
|
```go
|
|
func TestPublishRaw_NameRouting_NoSubscription(t *testing.T) {
|
|
p := &PubSub{
|
|
chorusTopicName: "CHORUS/coordination/v1",
|
|
hmmmTopicName: "hmmm/meta-discussion/v1",
|
|
contextTopicName: "CHORUS/context-feedback/v1",
|
|
}
|
|
if err := p.PublishRaw("nonexistent/topic", []byte("{}")); err == nil {
|
|
t.Fatalf("expected error for unknown topic")
|
|
}
|
|
}
|
|
```
|
|
|
|
### Integration Tests
|
|
|
|
See `/home/tony/chorus/project-queues/active/CHORUS/pkg/hmmm_adapter/integration_test.go` for full integration test examples.
|
|
|
|
## Related Documentation
|
|
|
|
- **P2P Package:** `/home/tony/chorus/project-queues/active/CHORUS/docs/comprehensive/packages/p2p.md` - Underlying libp2p networking
|
|
- **HMMM Package:** `/home/tony/chorus/project-queues/active/CHORUS/pkg/hmmm/` - HMMM meta-discussion system
|
|
- **SHHH Package:** `/home/tony/chorus/project-queues/active/CHORUS/pkg/shhh/` - Sensitive data redaction
|
|
- **Hypercore Package:** `/home/tony/chorus/project-queues/active/CHORUS/pkg/hcfs/hypercore.go` - Event persistence
|
|
|
|
## Implementation Details
|
|
|
|
### Concurrency
|
|
|
|
- All maps protected by RWMutex
|
|
- Goroutines for message handling (3 static + N dynamic)
|
|
- Context-based cancellation for clean shutdown
|
|
|
|
### Message Flow
|
|
|
|
```
|
|
Publisher PubSub Subscriber
|
|
| | |
|
|
|-- PublishBzzzMessage ---->| |
|
|
| |-- Sanitize (SHHH) -------->|
|
|
| |-- Marshal Message -------->|
|
|
| |-- GossipSub Publish ------>|
|
|
| | |
|
|
| |<-- GossipSub Receive ------|
|
|
| |-- Unmarshal Message ------>|
|
|
| |-- Filter Own Messages ---->|
|
|
| |-- handleBzzzMessages ----->|
|
|
| |-- Log to Hypercore ------->|
|
|
| |-- Call Handler ----------->|-- Process
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
- Network errors logged but not fatal
|
|
- Invalid messages logged and skipped
|
|
- Subscription errors cancel context
|
|
- Topic join errors returned immediately
|
|
|
|
## Source Files
|
|
|
|
- `/home/tony/chorus/project-queues/active/CHORUS/pubsub/pubsub.go` - Main implementation (942 lines)
|
|
- `/home/tony/chorus/project-queues/active/CHORUS/pubsub/adapter_hmmm.go` - HMMM adapter (41 lines)
|
|
- `/home/tony/chorus/project-queues/active/CHORUS/pubsub/pubsub_test.go` - Unit tests |