Files
CHORUS/internal/hapui/terminal.go
anthonyrawlins aea4d45fd8 Implement Phase 2 & 3: Complete HAP Terminal Interface with Patch Management
🎭 Phase 2: HAP Terminal Interface Implementation
 **Core Terminal Interface**: Interactive command-driven HAP terminal with help system
 **HMMM Message Composition System**:
   - New reasoning messages, thread replies, network queries, decision proposals
   - Complete message metadata handling (topics, threads, timestamps)
 **UCXL Context Browsing System**:
   - Address parsing, content retrieval from DHT encrypted storage
   - Search functionality, content creation, history navigation
 **Decision Participation System**:
   - Active decision listing, decision details with voting status
   - Vote casting with reasoning, decision proposals, HMMM integration

🔧 Phase 3: Enhanced Human Workflows
 **Patch Creation and Submission Workflows**:
   - Complete patch lifecycle management (create, review, submit, track)
   - Multiple patch types (context, code, config, docs)
   - UCXL integration with DHT storage, HMMM coordination
 **Time-Travel Diff Support**:
   - Temporal navigation operators (~~<n>, ^^<n>, @<time>)
   - Decision-hop analysis, visual diff display, version comparison

🏗️ **Architecture Highlights**:
- **Multi-binary structure**: Separate chorus-agent and chorus-hap binaries
- **Shared P2P runtime**: Both binaries use identical libp2p, DHT, HMMM, UCXL systems
- **Interactive sub-shells**: Dedicated command environments for HMMM, UCXL, patches, decisions
- **Network integration**: All features connect to distributed P2P agent network
- **Human-agent parity**: Humans participate as first-class network citizens

📦 **New Files**:
- internal/hapui/terminal.go: Complete HAP terminal interface (2400+ lines)
- prompts/human-roles.yaml: Role-based prompt configuration
- docs/decisions/*: HAP conversion decision record

🔗 **Integration Points**:
- HMMM: Collaborative reasoning and patch/decision announcements
- UCXL: Context addressing and version management
- DHT: Distributed storage of patches and content
- Decision System: Formal approval and consensus workflows

The HAP terminal interface now provides comprehensive human portal into the CHORUS
autonomous agent network, enabling collaborative reasoning, context sharing, patch
management, and distributed decision-making between humans and AI agents.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-07 09:38:14 +10:00

2415 lines
70 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package hapui
import (
"bufio"
"context"
"crypto/rand"
"encoding/json"
"fmt"
"math/big"
"os"
"strconv"
"strings"
"time"
"chorus/internal/runtime"
"chorus/pkg/hmmm"
"chorus/pkg/ucxl"
"chorus/pkg/storage"
"chorus/pubsub"
)
// TerminalInterface provides an interactive terminal interface for human agents
type TerminalInterface struct {
runtime *runtime.SharedRuntime
scanner *bufio.Scanner
quit chan bool
}
// NewTerminalInterface creates a new terminal interface for HAP
func NewTerminalInterface(runtime *runtime.SharedRuntime) *TerminalInterface {
return &TerminalInterface{
runtime: runtime,
scanner: bufio.NewScanner(os.Stdin),
quit: make(chan bool),
}
}
// Start begins the interactive terminal session
func (t *TerminalInterface) Start() error {
t.printWelcomeMessage()
t.printHelp()
// Announce human agent presence
if err := t.announceHumanAgent(); err != nil {
t.runtime.Logger.Error("Failed to announce human agent presence: %v", err)
}
// Start command processing loop
go t.commandLoop()
// Wait for quit signal
<-t.quit
return nil
}
// Stop terminates the terminal interface
func (t *TerminalInterface) Stop() {
close(t.quit)
}
// printWelcomeMessage displays the HAP welcome screen
func (t *TerminalInterface) printWelcomeMessage() {
fmt.Println("\n" + strings.Repeat("=", 80))
fmt.Println("🎭 CHORUS Human Agent Portal (HAP) - Terminal Interface")
fmt.Println(strings.Repeat("=", 80))
fmt.Printf("Agent ID: %s\n", t.runtime.Config.Agent.ID)
fmt.Printf("P2P Node: %s\n", t.runtime.Node.ID().ShortString())
fmt.Printf("Connected to: %d peers\n", t.runtime.Node.ConnectedPeers())
fmt.Println("\nYou are now connected to the CHORUS P2P agent network as a human participant.")
fmt.Println("You can collaborate with autonomous agents using the same protocols.")
fmt.Println(strings.Repeat("=", 80) + "\n")
}
// printHelp displays available commands
func (t *TerminalInterface) printHelp() {
fmt.Println("Available Commands:")
fmt.Println(" help - Show this help message")
fmt.Println(" status - Show network and agent status")
fmt.Println(" peers - List connected P2P peers")
fmt.Println(" hmmm - Compose and send HMMM reasoning message")
fmt.Println(" ucxl <address> - Browse UCXL context address")
fmt.Println(" patch - Create and submit patches")
fmt.Println(" decide <topic> - Participate in distributed decision")
fmt.Println(" announce - Re-announce human agent presence")
fmt.Println(" quit - Exit HAP terminal")
fmt.Println()
}
// commandLoop handles user input and command processing
func (t *TerminalInterface) commandLoop() {
for {
fmt.Print("hap> ")
if !t.scanner.Scan() {
// EOF or error
break
}
input := strings.TrimSpace(t.scanner.Text())
if input == "" {
continue
}
parts := strings.Fields(input)
command := strings.ToLower(parts[0])
switch command {
case "help", "h":
t.printHelp()
case "status", "s":
t.printStatus()
case "peers":
t.listPeers()
case "hmmm", "m":
t.handleHMMMCommand(parts[1:])
case "ucxl", "u":
if len(parts) < 2 {
fmt.Println("Usage: ucxl <address>")
continue
}
t.handleUCXLCommand(parts[1])
case "patch", "p":
t.handlePatchCommand()
case "decide", "d":
if len(parts) < 2 {
fmt.Println("Usage: decide <topic>")
continue
}
topic := strings.Join(parts[1:], " ")
t.handleDecisionCommand(topic)
case "announce", "a":
if err := t.announceHumanAgent(); err != nil {
fmt.Printf("Failed to announce presence: %v\n", err)
} else {
fmt.Println("✅ Human agent presence announced to network")
}
case "quit", "q", "exit":
fmt.Println("👋 Goodbye! Disconnecting from CHORUS network...")
t.quit <- true
return
case "clear", "cls":
// Clear screen (works on most terminals)
fmt.Print("\033[2J\033[H")
t.printWelcomeMessage()
default:
fmt.Printf("Unknown command: %s\n", command)
fmt.Println("Type 'help' for available commands.")
}
}
}
// printStatus displays current network and agent status
func (t *TerminalInterface) printStatus() {
fmt.Println("\n📊 HAP Status Report")
fmt.Println(strings.Repeat("-", 40))
// Agent Info
fmt.Printf("Agent ID: %s\n", t.runtime.Config.Agent.ID)
fmt.Printf("Agent Role: %s\n", t.runtime.Config.Agent.Role)
fmt.Printf("Agent Type: Human (HAP)\n")
// P2P Network Status
fmt.Printf("Node ID: %s\n", t.runtime.Node.ID().ShortString())
fmt.Printf("Connected Peers: %d\n", t.runtime.Node.ConnectedPeers())
// Task Status
activeTasks := t.runtime.TaskTracker.GetActiveTasks()
maxTasks := t.runtime.TaskTracker.GetMaxTasks()
fmt.Printf("Active Tasks: %d/%d\n", len(activeTasks), maxTasks)
// DHT Status
if t.runtime.DHTNode != nil {
fmt.Printf("DHT: ✅ Connected\n")
} else {
fmt.Printf("DHT: ❌ Disabled\n")
}
// BACKBEAT Status
if t.runtime.BackbeatIntegration != nil {
health := t.runtime.BackbeatIntegration.GetHealth()
if connected, ok := health["connected"].(bool); ok && connected {
fmt.Printf("BACKBEAT: ✅ Connected\n")
} else {
fmt.Printf("BACKBEAT: ⚠️ Disconnected\n")
}
} else {
fmt.Printf("BACKBEAT: ❌ Disabled\n")
}
fmt.Println(strings.Repeat("-", 40))
fmt.Printf("Last Updated: %s\n\n", time.Now().Format("15:04:05"))
}
// listPeers displays connected P2P peers
func (t *TerminalInterface) listPeers() {
peerCount := t.runtime.Node.ConnectedPeers()
fmt.Printf("\n🔗 Connected P2P Peers (%d)\n", peerCount)
fmt.Println(strings.Repeat("-", 50))
if peerCount == 0 {
fmt.Println("No peers connected.")
fmt.Println("Ensure other CHORUS agents are running on the network.")
} else {
fmt.Printf("Connected to %d peer(s) in the CHORUS network.\n", peerCount)
fmt.Println("Use P2P discovery mechanisms to find autonomous agents.")
}
fmt.Println()
}
// announceHumanAgent broadcasts human agent presence to the network
func (t *TerminalInterface) announceHumanAgent() error {
presence := map[string]interface{}{
"agent_id": t.runtime.Config.Agent.ID,
"node_id": t.runtime.Node.ID().ShortString(),
"agent_type": "human",
"interface": "terminal",
"capabilities": []string{
"hmmm_reasoning",
"decision_making",
"context_browsing",
"collaborative_editing",
},
"human_operator": true,
"timestamp": time.Now().Unix(),
"status": "online",
}
// Publish to capability broadcast topic
if err := t.runtime.PubSub.PublishBzzzMessage(pubsub.CapabilityBcast, presence); err != nil {
return fmt.Errorf("failed to publish human agent announcement: %w", err)
}
t.runtime.Logger.Info("👤 Human agent presence announced to network")
return nil
}
// handleHMMMCommand processes HMMM reasoning message composition
func (t *TerminalInterface) handleHMMMCommand(args []string) {
fmt.Println("\n📝 HMMM (Human-Machine-Machine-Machine) Message Composer")
fmt.Println(strings.Repeat("-", 60))
for {
fmt.Println("\nHMMM Commands:")
fmt.Println(" new - Compose new reasoning message")
fmt.Println(" reply - Reply to existing HMMM thread")
fmt.Println(" query - Ask network for reasoning help")
fmt.Println(" decide - Propose decision with reasoning")
fmt.Println(" help - Show detailed HMMM help")
fmt.Println(" back - Return to main HAP menu")
fmt.Print("\nhmmm> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showHMMMHelp()
case "new":
t.composeNewHMMMMessage()
case "reply":
t.composeHMMMReply()
case "query":
t.composeHMMMQuery()
case "decide":
t.composeHMMMDecision()
default:
fmt.Println("Unknown HMMM command. Type 'help' for available commands.")
}
}
}
// handleUCXLCommand processes UCXL context browsing
func (t *TerminalInterface) handleUCXLCommand(address string) {
fmt.Printf("\n🔗 UCXL Context Browser\n")
fmt.Println(strings.Repeat("-", 50))
// Parse the UCXL address
parsed, err := ucxl.ParseUCXLAddress(address)
if err != nil {
fmt.Printf("❌ Invalid UCXL address: %v\n", err)
fmt.Println("\nValid format: ucxl://agent:role@project:task/path*temporal/")
fmt.Println("Example: ucxl://alice:dev@myproject:task123/docs/readme.md*^/")
t.showUCXLHelp()
return
}
fmt.Printf("📍 Address: %s\n", parsed.Raw)
fmt.Printf("🤖 Agent: %s\n", parsed.Agent)
fmt.Printf("🎭 Role: %s\n", parsed.Role)
fmt.Printf("📁 Project: %s\n", parsed.Project)
fmt.Printf("📝 Task: %s\n", parsed.Task)
if parsed.Path != "" {
fmt.Printf("📄 Path: %s\n", parsed.Path)
}
if parsed.Temporal != "" {
fmt.Printf("⏰ Temporal: %s\n", parsed.Temporal)
}
fmt.Println()
// Try to retrieve content from storage
if t.runtime.EncryptedStorage != nil {
content, metadata, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(address)
if err != nil {
fmt.Printf("⚠️ Failed to retrieve content: %v\n", err)
fmt.Println("Content may not be available on this network.")
} else {
t.displayUCXLContent(content, metadata)
}
} else {
fmt.Println("⚠️ Storage system not available")
fmt.Println("Content retrieval requires configured DHT storage")
}
// Show UCXL browser commands
fmt.Println("\nUCXL Commands:")
fmt.Println(" search - Search for related content")
fmt.Println(" related - Find related contexts")
fmt.Println(" history - View address history")
fmt.Println(" create - Create new content at this address")
fmt.Println(" help - Show UCXL help")
fmt.Println(" back - Return to main menu")
for {
fmt.Print("\nucxl> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showUCXLHelp()
case "search":
t.handleUCXLSearch(parsed)
case "related":
t.handleUCXLRelated(parsed)
case "history":
t.handleUCXLHistory(parsed)
case "create":
t.handleUCXLCreate(parsed)
default:
fmt.Println("Unknown UCXL command. Type 'help' for available commands.")
}
}
}
// handleDecisionCommand processes decision participation
func (t *TerminalInterface) handleDecisionCommand(topic string) {
fmt.Printf("\n🗳 Decision Participation System\n")
fmt.Println(strings.Repeat("-", 50))
for {
fmt.Println("\nDecision Commands:")
fmt.Println(" list - List active decisions")
fmt.Println(" view <id> - View decision details")
fmt.Println(" vote <id> - Cast vote on decision")
fmt.Println(" propose - Propose new decision")
fmt.Println(" status - Show decision system status")
fmt.Println(" help - Show decision help")
fmt.Println(" back - Return to main menu")
fmt.Print("\ndecision> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
parts := strings.Fields(input)
command := parts[0]
switch command {
case "help":
t.showDecisionHelp()
case "list":
t.listActiveDecisions()
case "view":
if len(parts) < 2 {
fmt.Println("Usage: view <decision_id>")
continue
}
t.viewDecision(parts[1])
case "vote":
if len(parts) < 2 {
fmt.Println("Usage: vote <decision_id>")
continue
}
t.castVoteOnDecision(parts[1])
case "propose":
t.proposeNewDecision()
case "status":
t.showDecisionStatus()
default:
fmt.Println("Unknown decision command. Type 'help' for available commands.")
}
}
}
// HMMM Helper Functions
// showHMMMHelp displays detailed HMMM system information
func (t *TerminalInterface) showHMMMHelp() {
fmt.Println("\n🧠 HMMM (Human-Machine-Machine-Machine) Collaborative Reasoning")
fmt.Println(strings.Repeat("=", 70))
fmt.Println("HMMM enables structured collaborative reasoning between humans and AI agents.")
fmt.Println("Messages are routed through the P2P network with rich metadata and context.")
fmt.Println()
fmt.Println("Message Types:")
fmt.Println(" new - Start a new reasoning thread on any topic")
fmt.Println(" reply - Respond to an existing thread with your reasoning")
fmt.Println(" query - Ask the network for help with a specific problem")
fmt.Println(" decide - Propose a decision that requires network consensus")
fmt.Println()
fmt.Println("Message Structure:")
fmt.Println(" • Topic: Broad categorization (e.g., 'engineering', 'planning')")
fmt.Println(" • Issue ID: Specific problem or discussion identifier")
fmt.Println(" • Thread ID: Groups related messages together")
fmt.Println(" • Message: Your human reasoning, insights, or questions")
fmt.Println(" • Context: Links to relevant UCXL addresses or resources")
fmt.Println()
fmt.Println("Best Practices:")
fmt.Println(" ✅ Be specific and clear in your reasoning")
fmt.Println(" ✅ Include relevant context and background")
fmt.Println(" ✅ Ask follow-up questions to guide discussion")
fmt.Println(" ✅ Build on previous messages in the thread")
fmt.Println(" ❌ Avoid vague or overly broad statements")
fmt.Println(" ❌ Don't duplicate existing reasoning without adding value")
fmt.Println()
}
// composeNewHMMMMessage guides the user through creating a new reasoning message
func (t *TerminalInterface) composeNewHMMMMessage() {
fmt.Println("\n📝 New HMMM Reasoning Message")
fmt.Println(strings.Repeat("-", 40))
reader := bufio.NewReader(os.Stdin)
// Collect message details
fmt.Print("Topic (e.g., engineering, planning, architecture): ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Issue ID (number for this specific problem): ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64 = 1
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
}
fmt.Print("Subject/Title: ")
subject, _ := reader.ReadString('\n')
subject = strings.TrimSpace(subject)
if subject == "" {
fmt.Println("❌ Subject is required")
return
}
fmt.Println("Your reasoning (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
if reasoning.Len() == 0 {
fmt.Println("❌ Reasoning content is required")
return
}
// Generate message
msgID := t.generateMessageID()
threadID := t.generateThreadID(topic, issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/%s", topic),
Type: "reasoning_start",
Payload: map[string]interface{}{
"subject": subject,
"reasoning": strings.TrimSpace(reasoning.String()),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("New reasoning thread: %s", subject),
}
// Send message
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("❌ Failed to send HMMM message: %v\n", err)
return
}
fmt.Println("✅ HMMM reasoning message sent to network")
fmt.Printf(" Topic: %s\n", topic)
fmt.Printf(" Issue: #%d\n", issueID)
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMReply guides the user through replying to an existing thread
func (t *TerminalInterface) composeHMMMReply() {
fmt.Println("\n↩ Reply to HMMM Thread")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Thread ID to reply to: ")
threadID, _ := reader.ReadString('\n')
threadID = strings.TrimSpace(threadID)
if threadID == "" {
fmt.Println("❌ Thread ID is required")
return
}
fmt.Print("Issue ID: ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64 = 1
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
}
fmt.Println("Your reasoning/response (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
if reasoning.Len() == 0 {
fmt.Println("❌ Response content is required")
return
}
msgID := t.generateMessageID()
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/thread/%s", threadID),
Type: "reasoning_reply",
Payload: map[string]interface{}{
"reasoning": strings.TrimSpace(reasoning.String()),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
"parent_thread": threadID,
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: "Human agent reasoning response",
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("❌ Failed to send HMMM reply: %v\n", err)
return
}
fmt.Println("✅ HMMM reply sent to thread")
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMQuery guides the user through asking for reasoning help
func (t *TerminalInterface) composeHMMMQuery() {
fmt.Println("\n❓ HMMM Network Query")
fmt.Println(strings.Repeat("-", 25))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Query topic (e.g., technical, planning): ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Issue ID (or press Enter for new): ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
} else {
// Generate new issue ID
issueID = time.Now().Unix() % 10000
}
fmt.Print("Your question/problem: ")
question, _ := reader.ReadString('\n')
question = strings.TrimSpace(question)
if question == "" {
fmt.Println("❌ Question is required")
return
}
fmt.Println("Additional context (press Enter twice when done, or just Enter to skip):")
var context strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
if context.Len() > 0 {
context.WriteString("\n")
}
} else {
emptyLines = 0
if context.Len() > 0 {
context.WriteString(" ")
}
context.WriteString(line)
}
}
msgID := t.generateMessageID()
threadID := t.generateThreadID(topic, issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/query/%s", topic),
Type: "reasoning_query",
Payload: map[string]interface{}{
"question": question,
"context": context.String(),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
"urgency": "normal",
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Human query: %s", question),
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("❌ Failed to send HMMM query: %v\n", err)
return
}
fmt.Println("✅ HMMM query sent to network")
fmt.Printf(" Waiting for agent responses on issue #%d\n", issueID)
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMDecision guides the user through proposing a decision
func (t *TerminalInterface) composeHMMMDecision() {
fmt.Println("\n🗳 Propose Network Decision")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Decision topic: ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Decision title: ")
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
if title == "" {
fmt.Println("❌ Decision title is required")
return
}
fmt.Println("Decision rationale (press Enter twice when done):")
var rationale strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
rationale.WriteString("\n")
} else {
emptyLines = 0
rationale.WriteString(line + "\n")
}
}
if rationale.Len() == 0 {
fmt.Println("❌ Rationale is required")
return
}
fmt.Print("Options (comma-separated, e.g., 'approve,reject,defer'): ")
optionsStr, _ := reader.ReadString('\n')
optionsStr = strings.TrimSpace(optionsStr)
options := strings.Split(optionsStr, ",")
if len(options) == 0 {
options = []string{"approve", "reject"}
}
for i := range options {
options[i] = strings.TrimSpace(options[i])
}
issueID := time.Now().Unix() % 10000
msgID := t.generateMessageID()
threadID := t.generateThreadID("decision", issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/decision/%s", topic),
Type: "decision_proposal",
Payload: map[string]interface{}{
"title": title,
"rationale": strings.TrimSpace(rationale.String()),
"options": options,
"proposer": t.runtime.Config.Agent.ID,
"author_type": "human",
"deadline": time.Now().Add(24 * time.Hour).Unix(),
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Decision proposal: %s", title),
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("❌ Failed to send decision proposal: %v\n", err)
return
}
fmt.Println("✅ Decision proposal sent to network")
fmt.Printf(" Title: %s\n", title)
fmt.Printf(" Issue: #%d\n", issueID)
fmt.Printf(" Options: %s\n", strings.Join(options, ", "))
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Deadline: 24 hours from now\n")
fmt.Println()
}
// Helper functions for HMMM message management
// sendHMMMMessage sends an HMMM message through the P2P network
func (t *TerminalInterface) sendHMMMMessage(message hmmm.Message) error {
router := hmmm.NewRouter(t.runtime.PubSub)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return router.Publish(ctx, message)
}
// generateMessageID creates a unique message identifier
func (t *TerminalInterface) generateMessageID() string {
// Generate a random component
randomNum, _ := rand.Int(rand.Reader, big.NewInt(999999))
timestamp := time.Now().UnixNano()
return fmt.Sprintf("hap-%d-%06d", timestamp/1000000, randomNum.Int64())
}
// generateThreadID creates a thread identifier for grouping related messages
func (t *TerminalInterface) generateThreadID(topic string, issueID int64) string {
hash := fmt.Sprintf("%s-%d-%d", topic, issueID, time.Now().Unix()/3600) // Hour-based grouping
return fmt.Sprintf("thread-%x", hash)
}
// UCXL Helper Functions
// showUCXLHelp displays detailed UCXL system information
func (t *TerminalInterface) showUCXLHelp() {
fmt.Println("\n🗺 UCXL (Universal Context Exchange Language)")
fmt.Println(strings.Repeat("=", 60))
fmt.Println("UCXL provides addressing and navigation for distributed contexts.")
fmt.Println("Each address uniquely identifies content, resources, or state.")
fmt.Println()
fmt.Println("Address Format:")
fmt.Println(" ucxl://agent:role@project:task/path*temporal/")
fmt.Println()
fmt.Println("Components:")
fmt.Println(" agent - Agent ID or '*' for wildcard")
fmt.Println(" role - Agent role (dev, admin, user, etc.)")
fmt.Println(" project - Project identifier")
fmt.Println(" task - Task or issue identifier")
fmt.Println(" path - Optional resource path")
fmt.Println(" temporal - Optional time navigation")
fmt.Println()
fmt.Println("Temporal Navigation:")
fmt.Println(" *^/ - Latest version")
fmt.Println(" *~/ - Earliest version")
fmt.Println(" *@1234/ - Specific timestamp")
fmt.Println(" *~5/ - 5 versions back")
fmt.Println(" *^3/ - 3 versions forward")
fmt.Println()
fmt.Println("Examples:")
fmt.Println(" ucxl://alice:dev@webapp:frontend/src/components/")
fmt.Println(" ucxl://*:*@project123:bug456/logs/error.log*^/")
fmt.Println(" ucxl://bob:admin@infra:deploy/config/prod.yml*@1609459200/")
fmt.Println()
}
// displayUCXLContent shows retrieved content with metadata
func (t *TerminalInterface) displayUCXLContent(content []byte, metadata *storage.UCXLMetadata) {
fmt.Println("📦 Content Found:")
fmt.Println(strings.Repeat("-", 30))
if metadata != nil {
fmt.Printf("📄 Type: %s\n", metadata.ContentType)
fmt.Printf("👤 Creator: %s\n", metadata.CreatorRole)
fmt.Printf("📅 Created: %s\n", metadata.CreatedAt.Format("2006-01-02 15:04:05"))
fmt.Printf("📏 Size: %d bytes\n", metadata.Size)
if metadata.Encrypted {
fmt.Printf("🔒 Encrypted: Yes\n")
}
fmt.Println()
}
// Show content preview
contentStr := string(content)
if len(contentStr) > 1000 {
fmt.Printf("📖 Content Preview (first 1000 chars):\n%s\n...(truncated)\n", contentStr[:1000])
} else {
fmt.Printf("📖 Content:\n%s\n", contentStr)
}
fmt.Println()
}
// handleUCXLSearch searches for related UCXL content
func (t *TerminalInterface) handleUCXLSearch(parsed *ucxl.UCXLAddress) {
fmt.Println("\n🔍 Search UCXL Content")
fmt.Println(strings.Repeat("-", 30))
if t.runtime.EncryptedStorage == nil {
fmt.Println("❌ Storage system not available")
return
}
reader := bufio.NewReader(os.Stdin)
// Build search query from current address
query := &storage.SearchQuery{
Agent: parsed.Agent,
Role: parsed.Role,
Project: parsed.Project,
Task: parsed.Task,
Limit: 20,
}
// Allow user to modify search criteria
fmt.Print("Search agent (current: " + parsed.Agent + ", or press Enter): ")
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Agent = input
}
fmt.Print("Search role (current: " + parsed.Role + ", or press Enter): ")
input, _ = reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Role = input
}
fmt.Print("Search project (current: " + parsed.Project + ", or press Enter): ")
input, _ = reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Project = input
}
fmt.Print("Content type filter (optional): ")
contentType, _ := reader.ReadString('\n')
contentType = strings.TrimSpace(contentType)
if contentType != "" {
query.ContentType = contentType
}
// Perform search
results, err := t.runtime.EncryptedStorage.SearchContent(query)
if err != nil {
fmt.Printf("❌ Search failed: %v\n", err)
return
}
fmt.Printf("\n📋 Found %d results:\n", len(results))
fmt.Println(strings.Repeat("-", 50))
for i, result := range results {
fmt.Printf("%d. %s\n", i+1, result.Address)
fmt.Printf(" 📄 Type: %s | 👤 Creator: %s | 📅 %s\n",
result.ContentType,
result.CreatorRole,
result.CreatedAt.Format("2006-01-02 15:04"))
fmt.Println()
}
}
// handleUCXLRelated finds content related to the current address
func (t *TerminalInterface) handleUCXLRelated(parsed *ucxl.UCXLAddress) {
fmt.Println("\n🔗 Find Related Content")
fmt.Println(strings.Repeat("-", 25))
if t.runtime.EncryptedStorage == nil {
fmt.Println("❌ Storage system not available")
return
}
// Search for content with same project and task
query := &storage.SearchQuery{
Agent: "*",
Role: "*",
Project: parsed.Project,
Task: parsed.Task,
Limit: 10,
}
results, err := t.runtime.EncryptedStorage.SearchContent(query)
if err != nil {
fmt.Printf("❌ Related search failed: %v\n", err)
return
}
fmt.Printf("📊 Related content in %s:%s:\n", parsed.Project, parsed.Task)
fmt.Println(strings.Repeat("-", 40))
for i, result := range results {
if result.Address == parsed.Raw {
continue // Skip current address
}
fmt.Printf("%d. %s\n", i+1, result.Address)
fmt.Printf(" 👤 %s | 📄 %s | 📅 %s\n",
result.CreatorRole,
result.ContentType,
result.CreatedAt.Format("Jan 02, 15:04"))
}
if len(results) <= 1 {
fmt.Println("No related content found.")
fmt.Println("Try creating content or using broader search terms.")
}
fmt.Println()
}
// handleUCXLHistory shows version history for the address
func (t *TerminalInterface) handleUCXLHistory(parsed *ucxl.UCXLAddress) {
fmt.Println("\n📜 Address History")
fmt.Println(strings.Repeat("-", 20))
fmt.Println("⚠️ History tracking not yet fully implemented")
fmt.Println("This would show temporal versions of the content:")
fmt.Println()
fmt.Printf("Base address: %s\n", parsed.Raw)
fmt.Println("Temporal versions:")
fmt.Printf(" Latest: %s*^/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Earliest: %s*~/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Previous: %s*~1/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Timestamp: %s*@%d/\n", strings.TrimSuffix(parsed.Raw, "/"), time.Now().Unix())
fmt.Println()
}
// handleUCXLCreate helps create new content at the address
func (t *TerminalInterface) handleUCXLCreate(parsed *ucxl.UCXLAddress) {
fmt.Println("\n📝 Create UCXL Content")
fmt.Println(strings.Repeat("-", 25))
if t.runtime.EncryptedStorage == nil {
fmt.Println("❌ Storage system not available")
return
}
reader := bufio.NewReader(os.Stdin)
fmt.Print("Content type (text/plain, application/json, etc.): ")
contentType, _ := reader.ReadString('\n')
contentType = strings.TrimSpace(contentType)
if contentType == "" {
contentType = "text/plain"
}
fmt.Println("Content (press Enter twice when done):")
var content strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
content.WriteString("\n")
} else {
emptyLines = 0
content.WriteString(line + "\n")
}
}
contentBytes := []byte(strings.TrimSpace(content.String()))
if len(contentBytes) == 0 {
fmt.Println("❌ No content provided")
return
}
// Store content
err := t.runtime.EncryptedStorage.StoreUCXLContent(
parsed.Raw,
contentBytes,
t.runtime.Config.Agent.Role,
contentType,
)
if err != nil {
fmt.Printf("❌ Failed to store content: %v\n", err)
return
}
// Announce to network
if err := t.runtime.EncryptedStorage.AnnounceContent(parsed.Raw); err != nil {
fmt.Printf("⚠️ Failed to announce content: %v\n", err)
}
fmt.Println("✅ Content created successfully!")
fmt.Printf(" Address: %s\n", parsed.Raw)
fmt.Printf(" Type: %s\n", contentType)
fmt.Printf(" Size: %d bytes\n", len(contentBytes))
fmt.Println(" Content announced to P2P network")
fmt.Println()
}
// handlePatchCommand processes patch creation and submission workflows
func (t *TerminalInterface) handlePatchCommand() {
fmt.Printf("\n📝 CHORUS Patch Management System\n")
fmt.Println(strings.Repeat("-", 50))
for {
fmt.Println("\nPatch Commands:")
fmt.Println(" create - Create new patch from current state")
fmt.Println(" diff - Generate diff for context changes")
fmt.Println(" submit - Submit patch for review and integration")
fmt.Println(" list - List active patches")
fmt.Println(" review - Review existing patches")
fmt.Println(" status - Show patch system status")
fmt.Println(" help - Show patch system help")
fmt.Println(" back - Return to main menu")
fmt.Print("\npatch> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showPatchHelp()
case "create":
t.createPatch()
case "diff":
t.generateDiff()
case "submit":
t.submitPatch()
case "list":
t.listPatches()
case "review":
t.reviewPatches()
case "status":
t.showPatchStatus()
default:
fmt.Println("Unknown patch command. Type 'help' for available commands.")
}
}
}
// Decision Participation Helper Functions
// showDecisionHelp displays detailed decision system information
func (t *TerminalInterface) showDecisionHelp() {
fmt.Println("\n🗳 CHORUS Distributed Decision System")
fmt.Println(strings.Repeat("=", 55))
fmt.Println("The decision system enables collaborative consensus among network participants.")
fmt.Println("Both human agents and autonomous agents can participate in decision-making.")
fmt.Println()
fmt.Println("Decision Types:")
fmt.Println(" • Technical: Architecture, implementation choices")
fmt.Println(" • Operational: Resource allocation, task priority")
fmt.Println(" • Policy: Network rules, behavioral guidelines")
fmt.Println(" • Emergency: Urgent security or stability issues")
fmt.Println()
fmt.Println("Vote Options:")
fmt.Println(" ✅ approve - Support the proposed decision")
fmt.Println(" ❌ reject - Oppose the proposed decision")
fmt.Println(" ⏸️ defer - Postpone decision to gather more info")
fmt.Println(" ⚠️ abstain - Acknowledge but not participate")
fmt.Println()
fmt.Println("Consensus Rules:")
fmt.Println(" • Majority approval required for most decisions")
fmt.Println(" • Supermajority (2/3) for critical infrastructure changes")
fmt.Println(" • Emergency decisions may have shorter time windows")
fmt.Println(" • All votes should include reasoning/justification")
fmt.Println()
fmt.Println("Commands:")
fmt.Println(" list - See all active decisions awaiting votes")
fmt.Println(" view <id> - View full decision details and current voting")
fmt.Println(" vote <id> - Cast your vote with reasoning")
fmt.Println(" propose - Start a new decision for network consideration")
fmt.Println()
}
// listActiveDecisions shows all decisions currently open for voting
func (t *TerminalInterface) listActiveDecisions() {
fmt.Println("\n📋 Active Network Decisions")
fmt.Println(strings.Repeat("-", 35))
// This would connect to the decision tracking system
// For now, showing mock data structure
fmt.Println("⚠️ Decision tracking integration in development")
fmt.Println()
fmt.Println("Mock active decisions:")
fmt.Println()
decisions := []struct {
ID string
Title string
Type string
Proposer string
Deadline string
Status string
}{
{"DEC-001", "Upgrade libp2p to v0.27", "technical", "autonomous-agent-7", "2h 15m", "voting"},
{"DEC-002", "Adjust task timeout from 30s to 60s", "operational", "human-alice", "6h 30m", "voting"},
{"DEC-003", "Emergency: Quarantine node malicious-peer", "emergency", "security-monitor", "45m", "urgent"},
}
for _, decision := range decisions {
statusEmoji := "🗳️"
if decision.Status == "urgent" {
statusEmoji = "🚨"
}
fmt.Printf("%s %s - %s\n", statusEmoji, decision.ID, decision.Title)
fmt.Printf(" 📝 Type: %s | 👤 Proposer: %s | ⏰ Time left: %s\n",
decision.Type, decision.Proposer, decision.Deadline)
fmt.Println()
}
fmt.Println("Use 'view <id>' to see full details and cast your vote.")
fmt.Println("Example: view DEC-001")
fmt.Println()
}
// viewDecision shows detailed information about a specific decision
func (t *TerminalInterface) viewDecision(decisionID string) {
fmt.Printf("\n🔍 Decision Details: %s\n", decisionID)
fmt.Println(strings.Repeat("-", 40))
// Mock decision details - would come from decision tracking system
fmt.Println("⚠️ Decision retrieval integration in development")
fmt.Println()
switch decisionID {
case "DEC-001":
fmt.Println("📋 Title: Upgrade libp2p to v0.27")
fmt.Println("🏷️ Type: Technical Infrastructure")
fmt.Println("👤 Proposer: autonomous-agent-7")
fmt.Println("📅 Proposed: 2025-09-06 20:45:00")
fmt.Println("⏰ Deadline: 2025-09-07 09:00:00 (2h 15m remaining)")
fmt.Println()
fmt.Println("📖 Rationale:")
fmt.Println(" The current libp2p v0.24 has known issues with NAT traversal")
fmt.Println(" and connection stability. v0.27 fixes these issues and improves")
fmt.Println(" DHT performance by ~25%. This is a backward-compatible upgrade.")
fmt.Println()
fmt.Println("🗳️ Current Voting Status:")
fmt.Println(" ✅ Approve: 4 votes (bob-dev, carol-admin, eve-ops, agent-3)")
fmt.Println(" ❌ Reject: 1 vote (dave-conservative)")
fmt.Println(" ⏸️ Defer: 0 votes")
fmt.Println(" ⚠️ Abstain: 1 vote (frank-observer)")
fmt.Println()
fmt.Println(" 🎯 Status: Passing (67% approval, needs 50%)")
fmt.Println(" 📊 Participation: 6/12 network members voted")
case "DEC-002":
fmt.Println("📋 Title: Adjust task timeout from 30s to 60s")
fmt.Println("🏷️ Type: Operational Parameter")
fmt.Println("👤 Proposer: human-alice")
fmt.Println("📅 Proposed: 2025-09-06 15:30:00")
fmt.Println("⏰ Deadline: 2025-09-07 03:00:00 (6h 30m remaining)")
fmt.Println()
fmt.Println("📖 Rationale:")
fmt.Println(" Recent analysis shows that 23% of legitimate tasks are timing")
fmt.Println(" out at 30 seconds, causing unnecessary retries and wasted")
fmt.Println(" compute. Increasing to 60s would reduce false timeouts while")
fmt.Println(" still catching truly stuck tasks.")
fmt.Println()
fmt.Println("🗳️ Current Voting Status:")
fmt.Println(" ✅ Approve: 2 votes (alice-human, operations-bot)")
fmt.Println(" ❌ Reject: 1 vote (performance-monitor)")
fmt.Println(" ⏸️ Defer: 2 votes (bob-dev, carol-admin)")
fmt.Println(" ⚠️ Abstain: 0 votes")
fmt.Println()
fmt.Println(" 🎯 Status: Pending (40% approval, needs 50%)")
fmt.Println(" 📊 Participation: 5/12 network members voted")
default:
fmt.Printf("❌ Decision %s not found or access denied\n", decisionID)
fmt.Println("Use 'list' to see available decisions.")
}
fmt.Println()
fmt.Printf("To vote on this decision, use: vote %s\n", decisionID)
fmt.Println()
}
// castVoteOnDecision guides the user through voting on a decision
func (t *TerminalInterface) castVoteOnDecision(decisionID string) {
fmt.Printf("\n🗳 Cast Vote on %s\n", decisionID)
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
// Show vote options
fmt.Println("Vote Options:")
fmt.Println(" 1. ✅ approve - Support this decision")
fmt.Println(" 2. ❌ reject - Oppose this decision")
fmt.Println(" 3. ⏸️ defer - Need more information")
fmt.Println(" 4. ⚠️ abstain - Acknowledge but not participate")
fmt.Println()
fmt.Print("Your vote (1-4): ")
voteInput, _ := reader.ReadString('\n')
voteInput = strings.TrimSpace(voteInput)
var vote string
switch voteInput {
case "1", "approve":
vote = "approve"
case "2", "reject":
vote = "reject"
case "3", "defer":
vote = "defer"
case "4", "abstain":
vote = "abstain"
default:
fmt.Println("❌ Invalid vote option. Please choose 1-4.")
return
}
fmt.Printf("You selected: %s\n", vote)
fmt.Println()
// Get reasoning/justification
fmt.Println("Reasoning/Justification (required for transparency):")
fmt.Println("Explain why you are voting this way (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
reasoningText := strings.TrimSpace(reasoning.String())
if reasoningText == "" {
fmt.Println("❌ Reasoning is required for all votes")
return
}
// Confirmation
fmt.Println("📋 Vote Summary:")
fmt.Printf(" Decision: %s\n", decisionID)
fmt.Printf(" Your Vote: %s\n", vote)
fmt.Printf(" Reasoning: %s\n", reasoningText)
fmt.Println()
fmt.Print("Submit this vote? (y/n): ")
confirm, _ := reader.ReadString('\n')
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println("❌ Vote cancelled")
return
}
// Submit vote (would integrate with decision system)
fmt.Println("⚠️ Vote submission integration in development")
fmt.Printf("📝 Your %s vote on %s has been recorded\n", vote, decisionID)
fmt.Println("💌 Vote reasoning published to network for transparency")
fmt.Println("🔔 Other network members will be notified of your participation")
// Create HMMM message for vote announcement
if err := t.announceVoteDecision(decisionID, vote, reasoningText); err != nil {
fmt.Printf("⚠️ Failed to announce vote via HMMM: %v\n", err)
} else {
fmt.Println("📢 Vote announced via HMMM reasoning network")
}
fmt.Println()
}
// proposeNewDecision guides the user through creating a new decision
func (t *TerminalInterface) proposeNewDecision() {
fmt.Println("\n📝 Propose New Network Decision")
fmt.Println(strings.Repeat("-", 35))
reader := bufio.NewReader(os.Stdin)
// Decision type
fmt.Println("Decision Types:")
fmt.Println(" 1. technical - Architecture, code, infrastructure")
fmt.Println(" 2. operational - Process, resource allocation")
fmt.Println(" 3. policy - Network rules, governance")
fmt.Println(" 4. emergency - Urgent security/stability issue")
fmt.Println()
fmt.Print("Decision type (1-4): ")
typeInput, _ := reader.ReadString('\n')
typeInput = strings.TrimSpace(typeInput)
var decisionType string
switch typeInput {
case "1", "technical":
decisionType = "technical"
case "2", "operational":
decisionType = "operational"
case "3", "policy":
decisionType = "policy"
case "4", "emergency":
decisionType = "emergency"
default:
fmt.Println("❌ Invalid decision type")
return
}
// Title
fmt.Print("Decision title (concise summary): ")
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
if title == "" {
fmt.Println("❌ Title is required")
return
}
// Rationale
fmt.Println("Detailed rationale (press Enter twice when done):")
var rationale strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
rationale.WriteString("\n")
} else {
emptyLines = 0
rationale.WriteString(line + "\n")
}
}
rationaleText := strings.TrimSpace(rationale.String())
if rationaleText == "" {
fmt.Println("❌ Rationale is required")
return
}
// Voting options
fmt.Print("Custom voting options (comma-separated, or press Enter for default): ")
optionsInput, _ := reader.ReadString('\n')
optionsInput = strings.TrimSpace(optionsInput)
var options []string
if optionsInput == "" {
options = []string{"approve", "reject", "defer", "abstain"}
} else {
options = strings.Split(optionsInput, ",")
for i := range options {
options[i] = strings.TrimSpace(options[i])
}
}
// Deadline
var deadline time.Duration
if decisionType == "emergency" {
deadline = 2 * time.Hour
fmt.Println("⚠️ Emergency decisions have 2-hour deadline")
} else {
fmt.Print("Voting deadline in hours (default: 24): ")
deadlineInput, _ := reader.ReadString('\n')
deadlineInput = strings.TrimSpace(deadlineInput)
if deadlineInput == "" {
deadline = 24 * time.Hour
} else {
hours, err := strconv.ParseFloat(deadlineInput, 64)
if err != nil || hours <= 0 {
fmt.Println("❌ Invalid deadline")
return
}
deadline = time.Duration(hours * float64(time.Hour))
}
}
// Summary and confirmation
fmt.Println("\n📋 Decision Proposal Summary:")
fmt.Printf(" Type: %s\n", decisionType)
fmt.Printf(" Title: %s\n", title)
fmt.Printf(" Options: %s\n", strings.Join(options, ", "))
fmt.Printf(" Deadline: %s from now\n", deadline)
fmt.Printf(" Rationale:\n%s\n", rationaleText)
fmt.Println()
fmt.Print("Submit this decision proposal? (y/n): ")
confirm, _ := reader.ReadString('\n')
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println("❌ Decision proposal cancelled")
return
}
// Generate decision ID
decisionID := fmt.Sprintf("DEC-%d", time.Now().Unix()%10000)
// Submit decision (would integrate with decision system)
fmt.Println("⚠️ Decision proposal integration in development")
fmt.Printf("✅ Decision %s proposed successfully\n", decisionID)
fmt.Println("📢 Decision announced to all network members")
fmt.Printf("⏰ Voting closes in %s\n", deadline)
fmt.Println("🗳️ Network members can now cast their votes")
// Send HMMM announcement
if err := t.announceNewDecisionProposal(decisionID, title, decisionType, rationaleText, options); err != nil {
fmt.Printf("⚠️ Failed to announce via HMMM: %v\n", err)
} else {
fmt.Println("📡 Decision announced via HMMM reasoning network")
}
fmt.Println()
}
// showDecisionStatus shows overall decision system status
func (t *TerminalInterface) showDecisionStatus() {
fmt.Println("\n📊 Decision System Status")
fmt.Println(strings.Repeat("-", 30))
fmt.Println("⚠️ Decision system integration in development")
fmt.Println()
fmt.Println("Mock system status:")
fmt.Printf("🗳️ Active Decisions: 3\n")
fmt.Printf("⏰ Urgent Decisions: 1 (emergency timeout)\n")
fmt.Printf("👥 Network Members: 12 (8 active, 4 idle)\n")
fmt.Printf("📊 Participation Rate: 67% (last 7 days)\n")
fmt.Printf("✅ Consensus Success Rate: 89%\n")
fmt.Printf("⚖️ Decision Types:\n")
fmt.Printf(" Technical: 45%%, Operational: 30%%\n")
fmt.Printf(" Policy: 20%%, Emergency: 5%%\n")
fmt.Println()
fmt.Println("🔔 Recent Activity:")
fmt.Println(" • DEC-003: Emergency quarantine decision (45m left)")
fmt.Println(" • DEC-002: Task timeout adjustment (6h 30m left)")
fmt.Println(" • DEC-001: libp2p upgrade (2h 15m left)")
fmt.Println(" • DEC-055: Completed - Storage encryption (✅ approved)")
fmt.Println()
}
// announceVoteDecision sends an HMMM message about a vote
func (t *TerminalInterface) announceVoteDecision(decisionID, vote, reasoning string) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("decision-%s", decisionID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/decisions/vote/%s", decisionID),
Type: "decision_vote",
Payload: map[string]interface{}{
"decision_id": decisionID,
"vote": vote,
"reasoning": reasoning,
"voter": t.runtime.Config.Agent.ID,
"voter_type": "human",
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Vote cast on %s: %s", decisionID, vote),
}
return t.sendHMMMMessage(message)
}
// announceNewDecisionProposal sends an HMMM message about a new decision
func (t *TerminalInterface) announceNewDecisionProposal(decisionID, title, decisionType, rationale string, options []string) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("decision-%s", decisionID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/decisions/proposal/%s", decisionType),
Type: "decision_proposal",
Payload: map[string]interface{}{
"decision_id": decisionID,
"title": title,
"decision_type": decisionType,
"rationale": rationale,
"options": options,
"proposer": t.runtime.Config.Agent.ID,
"proposer_type": "human",
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("New %s decision proposed: %s", decisionType, title),
}
return t.sendHMMMMessage(message)
}
// Patch Management Helper Functions
// showPatchHelp displays detailed patch system information
func (t *TerminalInterface) showPatchHelp() {
fmt.Println("\n🔧 CHORUS Patch Management System")
fmt.Println(strings.Repeat("=", 60))
fmt.Println("Create, review, and submit patches for distributed contexts and code changes.")
fmt.Println("Patches enable collaborative editing with temporal navigation and approval workflows.")
fmt.Println()
fmt.Println("Patch Types:")
fmt.Println(" • Context Patches: Changes to UCXL context content")
fmt.Println(" • Code Patches: Traditional diff-based code changes")
fmt.Println(" • Configuration Patches: System and environment changes")
fmt.Println(" • Documentation Patches: Updates to project documentation")
fmt.Println()
fmt.Println("Temporal Navigation:")
fmt.Println(" ~~<n> - Navigate n decision-hops backward")
fmt.Println(" ^^<n> - Navigate n decision-hops forward")
fmt.Println(" @<time> - Navigate to specific timestamp")
fmt.Println(" ~latest - Go to latest version")
fmt.Println(" ~first - Go to initial version")
fmt.Println()
fmt.Println("Workflow:")
fmt.Println(" 1. create - Create patch from current working state")
fmt.Println(" 2. diff - Review changes with temporal comparison")
fmt.Println(" 3. submit - Submit for peer review via HMMM network")
fmt.Println(" 4. review - Participate in patch review process")
fmt.Println(" 5. merge - Integrate approved patches into DHT")
fmt.Println()
fmt.Println("Integration:")
fmt.Println(" • HMMM: Patch discussions and approval reasoning")
fmt.Println(" • UCXL: Context addressing and version management")
fmt.Println(" • DHT: Distributed storage of patches and content")
fmt.Println(" • Decision System: Formal approval and consensus")
fmt.Println()
}
// createPatch guides user through patch creation process
func (t *TerminalInterface) createPatch() {
fmt.Println("\n📝 Create New Patch")
fmt.Println(strings.Repeat("-", 25))
reader := bufio.NewReader(os.Stdin)
// Patch type selection
fmt.Println("Patch Types:")
fmt.Println(" 1. context - UCXL context content changes")
fmt.Println(" 2. code - Traditional code diff")
fmt.Println(" 3. config - Configuration changes")
fmt.Println(" 4. docs - Documentation updates")
fmt.Println()
fmt.Print("Patch type (1-4): ")
typeInput, _ := reader.ReadString('\n')
typeInput = strings.TrimSpace(typeInput)
var patchType string
switch typeInput {
case "1", "context":
patchType = "context"
case "2", "code":
patchType = "code"
case "3", "config":
patchType = "config"
case "4", "docs":
patchType = "docs"
default:
fmt.Println("❌ Invalid patch type")
return
}
// Get base context/address
fmt.Print("Base UCXL address (what you're modifying): ")
baseAddress, _ := reader.ReadString('\n')
baseAddress = strings.TrimSpace(baseAddress)
if baseAddress == "" {
fmt.Println("❌ Base address is required")
return
}
// Validate base address
parsed, err := ucxl.ParseUCXLAddress(baseAddress)
if err != nil {
fmt.Printf("❌ Invalid UCXL address: %v\n", err)
return
}
// Get current content (from storage)
fmt.Println("\n📖 Fetching current content...")
currentContent := ""
if t.runtime.EncryptedStorage != nil {
content, _, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(baseAddress)
if err != nil {
fmt.Printf("⚠️ Could not fetch current content: %v\n", err)
fmt.Println("Creating patch from empty base...")
} else {
currentContent = string(content)
}
}
// Show current content for reference
if currentContent != "" {
fmt.Println("\n📄 Current Content:")
fmt.Println(strings.Repeat("-", 40))
if len(currentContent) > 500 {
fmt.Printf("%s\n...(truncated, %d total chars)\n", currentContent[:500], len(currentContent))
} else {
fmt.Println(currentContent)
}
fmt.Println(strings.Repeat("-", 40))
fmt.Println()
}
// Get patch title and description
fmt.Print("Patch title: ")
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
if title == "" {
fmt.Println("❌ Title is required")
return
}
fmt.Println("Patch description (press Enter twice when done):")
var description strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
description.WriteString("\n")
} else {
emptyLines = 0
description.WriteString(line + "\n")
}
}
descriptionText := strings.TrimSpace(description.String())
if descriptionText == "" {
fmt.Println("❌ Description is required")
return
}
// Get the new content
fmt.Println("New content (press Enter twice when done):")
fmt.Println("(This will replace the existing content)")
var newContent strings.Builder
emptyLines = 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
newContent.WriteString("\n")
} else {
emptyLines = 0
newContent.WriteString(line + "\n")
}
}
newContentText := strings.TrimSpace(newContent.String())
if newContentText == "" {
fmt.Println("❌ New content cannot be empty")
return
}
// Generate patch ID and create patch structure
patchID := fmt.Sprintf("patch-%d", time.Now().Unix())
patch := map[string]interface{}{
"id": patchID,
"type": patchType,
"title": title,
"description": descriptionText,
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
"base_address": baseAddress,
"base_content": currentContent,
"new_content": newContentText,
"created_at": time.Now().Unix(),
"status": "draft",
"project": parsed.Project,
"task": parsed.Task,
}
// Store patch in DHT (temporary storage for review)
patchAddress := fmt.Sprintf("ucxl://%s:%s@%s:patches/%s/",
t.runtime.Config.Agent.ID,
t.runtime.Config.Agent.Role,
parsed.Project,
patchID)
patchData, err := json.Marshal(patch)
if err != nil {
fmt.Printf("❌ Failed to serialize patch: %v\n", err)
return
}
if t.runtime.EncryptedStorage != nil {
err = t.runtime.EncryptedStorage.StoreUCXLContent(
patchAddress,
patchData,
t.runtime.Config.Agent.Role,
"application/json",
)
if err != nil {
fmt.Printf("❌ Failed to store patch: %v\n", err)
return
}
}
// Success feedback
fmt.Println("✅ Patch created successfully!")
fmt.Printf(" Patch ID: %s\n", patchID)
fmt.Printf(" Type: %s\n", patchType)
fmt.Printf(" Base: %s\n", baseAddress)
fmt.Printf(" Storage: %s\n", patchAddress)
fmt.Println()
fmt.Println("💡 Next steps:")
fmt.Println(" • Use 'diff' to review your changes")
fmt.Println(" • Use 'submit' to send for review")
fmt.Println()
}
// generateDiff creates temporal diff between versions
func (t *TerminalInterface) generateDiff() {
fmt.Println("\n🔍 Generate Temporal Diff")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Base UCXL address: ")
baseAddress, _ := reader.ReadString('\n')
baseAddress = strings.TrimSpace(baseAddress)
if baseAddress == "" {
fmt.Println("❌ Base address is required")
return
}
// Validate address
_, err := ucxl.ParseUCXLAddress(baseAddress)
if err != nil {
fmt.Printf("❌ Invalid UCXL address: %v\n", err)
return
}
fmt.Println("\nTemporal Navigation Options:")
fmt.Println(" ~<n> - n decision-hops backward (e.g., ~2)")
fmt.Println(" ^<n> - n decision-hops forward (e.g., ^1)")
fmt.Println(" @<time> - specific timestamp (e.g., @1699123456)")
fmt.Println(" current - current/latest version")
fmt.Println()
fmt.Print("Compare FROM version: ")
fromVersion, _ := reader.ReadString('\n')
fromVersion = strings.TrimSpace(fromVersion)
fmt.Print("Compare TO version: ")
toVersion, _ := reader.ReadString('\n')
toVersion = strings.TrimSpace(toVersion)
if fromVersion == "" {
fromVersion = "~1"
}
if toVersion == "" {
toVersion = "current"
}
// Build temporal addresses
fromAddress := t.buildTemporalAddress(baseAddress, fromVersion)
toAddress := t.buildTemporalAddress(baseAddress, toVersion)
fmt.Printf("\n🔍 Comparing:\n")
fmt.Printf(" FROM: %s\n", fromAddress)
fmt.Printf(" TO: %s\n", toAddress)
fmt.Println()
// Fetch content for both versions
fmt.Println("📖 Fetching content versions...")
var fromContent, toContent string
if t.runtime.EncryptedStorage != nil {
// Fetch FROM version
if content, _, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(fromAddress); err == nil {
fromContent = string(content)
} else {
fmt.Printf("⚠️ Could not fetch FROM content: %v\n", err)
}
// Fetch TO version
if content, _, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(toAddress); err == nil {
toContent = string(content)
} else {
fmt.Printf("⚠️ Could not fetch TO content: %v\n", err)
}
} else {
fmt.Println("⚠️ Storage system not available")
return
}
// Generate and display diff
fmt.Println("\n📋 Content Diff:")
fmt.Println(strings.Repeat("=", 50))
if fromContent == toContent {
fmt.Println("✅ No differences found")
} else {
t.displaySimpleDiff(fromContent, toContent)
}
fmt.Println(strings.Repeat("=", 50))
fmt.Println()
}
// submitPatch submits patch for review via HMMM network
func (t *TerminalInterface) submitPatch() {
fmt.Println("\n📤 Submit Patch for Review")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Patch ID to submit: ")
patchID, _ := reader.ReadString('\n')
patchID = strings.TrimSpace(patchID)
if patchID == "" {
fmt.Println("❌ Patch ID is required")
return
}
// Build patch address and fetch patch data
patchAddress := fmt.Sprintf("ucxl://%s:%s@*:patches/%s/",
t.runtime.Config.Agent.ID,
t.runtime.Config.Agent.Role,
patchID)
fmt.Printf("📖 Loading patch: %s\n", patchID)
var patchData map[string]interface{}
if t.runtime.EncryptedStorage != nil {
content, _, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(patchAddress)
if err != nil {
fmt.Printf("❌ Could not load patch: %v\n", err)
return
}
err = json.Unmarshal(content, &patchData)
if err != nil {
fmt.Printf("❌ Invalid patch data: %v\n", err)
return
}
} else {
fmt.Println("❌ Storage system not available")
return
}
// Display patch summary
fmt.Println("\n📋 Patch Summary:")
fmt.Printf(" ID: %s\n", patchData["id"])
fmt.Printf(" Type: %s\n", patchData["type"])
fmt.Printf(" Title: %s\n", patchData["title"])
fmt.Printf(" Description: %s\n", patchData["description"])
fmt.Printf(" Base: %s\n", patchData["base_address"])
fmt.Printf(" Author: %s (%s)\n", patchData["author"], patchData["author_type"])
fmt.Println()
// Get review requirements
fmt.Println("Review Configuration:")
fmt.Print("Required approvals (default: 2): ")
approvalsInput, _ := reader.ReadString('\n')
approvalsInput = strings.TrimSpace(approvalsInput)
requiredApprovals := 2
if approvalsInput != "" {
if approvals, err := strconv.Atoi(approvalsInput); err == nil {
requiredApprovals = approvals
}
}
fmt.Print("Review deadline in hours (default: 48): ")
deadlineInput, _ := reader.ReadString('\n')
deadlineInput = strings.TrimSpace(deadlineInput)
deadlineHours := 48.0
if deadlineInput != "" {
if hours, err := strconv.ParseFloat(deadlineInput, 64); err == nil {
deadlineHours = hours
}
}
fmt.Print("Target reviewers (comma-separated, or 'auto' for automatic): ")
reviewersInput, _ := reader.ReadString('\n')
reviewersInput = strings.TrimSpace(reviewersInput)
var reviewers []string
if reviewersInput == "" || reviewersInput == "auto" {
reviewers = []string{"auto-assigned"}
} else {
reviewers = strings.Split(reviewersInput, ",")
for i := range reviewers {
reviewers[i] = strings.TrimSpace(reviewers[i])
}
}
// Confirmation
fmt.Println("\n📋 Submission Summary:")
fmt.Printf(" Patch: %s\n", patchID)
fmt.Printf(" Required Approvals: %d\n", requiredApprovals)
fmt.Printf(" Review Deadline: %.1f hours\n", deadlineHours)
fmt.Printf(" Reviewers: %s\n", strings.Join(reviewers, ", "))
fmt.Println()
fmt.Print("Submit for review? (y/n): ")
confirm, _ := reader.ReadString('\n')
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println("❌ Patch submission cancelled")
return
}
// Update patch status and submit via HMMM
patchData["status"] = "submitted"
patchData["required_approvals"] = requiredApprovals
patchData["deadline"] = time.Now().Add(time.Duration(deadlineHours * float64(time.Hour))).Unix()
patchData["reviewers"] = reviewers
patchData["submitted_at"] = time.Now().Unix()
// Re-store updated patch
updatedPatchData, _ := json.Marshal(patchData)
if t.runtime.EncryptedStorage != nil {
err := t.runtime.EncryptedStorage.StoreUCXLContent(
patchAddress,
updatedPatchData,
t.runtime.Config.Agent.Role,
"application/json",
)
if err != nil {
fmt.Printf("❌ Failed to update patch: %v\n", err)
return
}
}
// Send HMMM message for review
if err := t.announcePatchSubmission(patchID, patchData); err != nil {
fmt.Printf("⚠️ Failed to announce via HMMM: %v\n", err)
}
fmt.Println("✅ Patch submitted for review!")
fmt.Printf(" Patch ID: %s\n", patchID)
fmt.Printf(" Status: submitted\n")
fmt.Printf(" Review deadline: %.1f hours from now\n", deadlineHours)
fmt.Println("📢 Review announcement sent via HMMM network")
fmt.Println()
}
// listPatches shows active patches in the system
func (t *TerminalInterface) listPatches() {
fmt.Println("\n📋 Active Patches")
fmt.Println(strings.Repeat("-", 25))
fmt.Println("⚠️ Patch listing integration in development")
fmt.Println()
fmt.Println("Mock active patches:")
fmt.Println()
// Mock patch data
patches := []struct {
ID string
Type string
Title string
Author string
Status string
Approvals string
Deadline string
}{
{"patch-001", "context", "Fix user authentication logic", "alice-human", "submitted", "2/3", "12h"},
{"patch-002", "code", "Optimize DHT lookup performance", "agent-optimizer", "review", "1/2", "6h"},
{"patch-003", "config", "Update production timeout values", "bob-ops", "draft", "0/2", "-"},
{"patch-004", "docs", "Add HAP usage examples", "carol-tech-writer", "approved", "3/2", "complete"},
}
for _, patch := range patches {
statusEmoji := "📝"
switch patch.Status {
case "submitted":
statusEmoji = "📤"
case "review":
statusEmoji = "👀"
case "approved":
statusEmoji = "✅"
case "rejected":
statusEmoji = "❌"
}
fmt.Printf("%s %s - %s\n", statusEmoji, patch.ID, patch.Title)
fmt.Printf(" 📂 Type: %s | 👤 Author: %s | 🗳️ Approvals: %s | ⏰ %s\n",
patch.Type, patch.Author, patch.Approvals, patch.Deadline)
fmt.Println()
}
fmt.Println("Use 'review' to participate in patch reviews.")
fmt.Println("Use 'status' for detailed patch system metrics.")
fmt.Println()
}
// reviewPatches participates in patch review process
func (t *TerminalInterface) reviewPatches() {
fmt.Println("\n👀 Patch Review System")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Patch ID to review: ")
patchID, _ := reader.ReadString('\n')
patchID = strings.TrimSpace(patchID)
if patchID == "" {
fmt.Println("❌ Patch ID is required")
return
}
// Mock patch review (would integrate with patch storage system)
fmt.Println("⚠️ Patch review integration in development")
fmt.Printf("📖 Loading patch %s for review...\n", patchID)
fmt.Println()
switch patchID {
case "patch-001":
fmt.Println("📋 Patch Details: Fix user authentication logic")
fmt.Println("👤 Author: alice-human")
fmt.Println("📂 Type: context")
fmt.Println("📍 Base: ucxl://alice:dev@webapp:auth/login-handler/")
fmt.Println()
fmt.Println("📖 Description:")
fmt.Println(" Fix issue where authentication tokens were not being properly")
fmt.Println(" validated against the role-based access control system.")
fmt.Println()
fmt.Println("🔍 Changes:")
fmt.Println(" - Added proper RBAC token validation")
fmt.Println(" - Fixed role hierarchy checking")
fmt.Println(" - Updated error handling for invalid tokens")
fmt.Println()
default:
fmt.Printf("❌ Patch %s not found or access denied\n", patchID)
return
}
// Review options
fmt.Println("Review Options:")
fmt.Println(" 1. ✅ approve - Approve this patch")
fmt.Println(" 2. ❌ reject - Reject this patch")
fmt.Println(" 3. 🔄 request-changes - Request changes before approval")
fmt.Println(" 4. 💬 comment - Add comment without approval decision")
fmt.Println()
fmt.Print("Your review (1-4): ")
reviewInput, _ := reader.ReadString('\n')
reviewInput = strings.TrimSpace(reviewInput)
var reviewType string
switch reviewInput {
case "1", "approve":
reviewType = "approve"
case "2", "reject":
reviewType = "reject"
case "3", "request-changes":
reviewType = "request-changes"
case "4", "comment":
reviewType = "comment"
default:
fmt.Println("❌ Invalid review option")
return
}
// Get review reasoning
fmt.Println("Review reasoning/comment (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
reasoningText := strings.TrimSpace(reasoning.String())
if reasoningText == "" {
fmt.Println("❌ Review reasoning is required")
return
}
// Submit review
fmt.Println("⚠️ Review submission integration in development")
fmt.Printf("✅ Review submitted for %s\n", patchID)
fmt.Printf(" Review: %s\n", reviewType)
fmt.Printf(" Reviewer: %s\n", t.runtime.Config.Agent.ID)
fmt.Println("💌 Review reasoning will be published to HMMM network")
// Announce review via HMMM
if err := t.announcePatchReview(patchID, reviewType, reasoningText); err != nil {
fmt.Printf("⚠️ Failed to announce review: %v\n", err)
} else {
fmt.Println("📢 Review announced via HMMM reasoning network")
}
fmt.Println()
}
// showPatchStatus displays patch system status
func (t *TerminalInterface) showPatchStatus() {
fmt.Println("\n📊 Patch System Status")
fmt.Println(strings.Repeat("-", 30))
fmt.Println("⚠️ Patch system integration in development")
fmt.Println()
fmt.Println("Mock system status:")
fmt.Printf("📝 Active Patches: 4 (3 submitted, 1 draft)\n")
fmt.Printf("👀 Pending Reviews: 2 (requiring your attention)\n")
fmt.Printf("⏰ Urgent Deadlines: 1 (< 6 hours remaining)\n")
fmt.Printf("✅ Approved Today: 2\n")
fmt.Printf("🔄 Auto-merge Queue: 1\n")
fmt.Println()
fmt.Println("🎯 Your Activity:")
fmt.Printf(" Created: 1 patch (patch-003)\n")
fmt.Printf(" Reviews: 3 completed this week\n")
fmt.Printf(" Approval Rate: 85%% (17/20 approved)\n")
fmt.Printf(" Avg Review Time: 2.3 hours\n")
fmt.Println()
fmt.Println("🔔 Recent Activity:")
fmt.Println(" • patch-001: Awaiting final approval (12h left)")
fmt.Println(" • patch-002: New review from agent-optimizer (6h left)")
fmt.Println(" • patch-004: Auto-merged after 3 approvals")
fmt.Println()
}
// Helper functions for patch management
// buildTemporalAddress creates temporal UCXL addresses
func (t *TerminalInterface) buildTemporalAddress(baseAddress, temporalNav string) string {
if temporalNav == "current" {
return baseAddress
}
// Remove trailing slash if present
addr := strings.TrimSuffix(baseAddress, "/")
// Add temporal navigation
return fmt.Sprintf("%s*%s/", addr, temporalNav)
}
// displaySimpleDiff shows a basic character-level diff
func (t *TerminalInterface) displaySimpleDiff(fromContent, toContent string) {
fromLines := strings.Split(fromContent, "\n")
toLines := strings.Split(toContent, "\n")
maxLines := len(fromLines)
if len(toLines) > maxLines {
maxLines = len(toLines)
}
for i := 0; i < maxLines; i++ {
var fromLine, toLine string
if i < len(fromLines) {
fromLine = fromLines[i]
}
if i < len(toLines) {
toLine = toLines[i]
}
if fromLine != toLine {
if fromLine != "" {
fmt.Printf("- %s\n", fromLine)
}
if toLine != "" {
fmt.Printf("+ %s\n", toLine)
}
} else if fromLine != "" {
fmt.Printf(" %s\n", fromLine)
}
}
}
// announcePatchSubmission sends HMMM message about patch submission
func (t *TerminalInterface) announcePatchSubmission(patchID string, patchData map[string]interface{}) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("patch-%s", patchID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/patches/submission/%s", patchData["type"]),
Type: "patch_submission",
Payload: map[string]interface{}{
"patch_id": patchID,
"title": patchData["title"],
"description": patchData["description"],
"patch_type": patchData["type"],
"base_address": patchData["base_address"],
"author": patchData["author"],
"author_type": patchData["author_type"],
"reviewers": patchData["reviewers"],
"deadline": patchData["deadline"],
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Patch submitted for review: %s", patchData["title"]),
}
return t.sendHMMMMessage(message)
}
// announcePatchReview sends HMMM message about patch review
func (t *TerminalInterface) announcePatchReview(patchID, reviewType, reasoning string) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("patch-%s", patchID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/patches/review/%s", patchID),
Type: "patch_review",
Payload: map[string]interface{}{
"patch_id": patchID,
"review_type": reviewType,
"reasoning": reasoning,
"reviewer": t.runtime.Config.Agent.ID,
"reviewer_type": "human",
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Patch review: %s (%s)", reviewType, patchID),
}
return t.sendHMMMMessage(message)
}