Skip to content

Latest commit

 

History

History
961 lines (751 loc) · 20.8 KB

File metadata and controls

961 lines (751 loc) · 20.8 KB

Resonance Graph Visualization Specification

Version: 1.0.0 Status: Draft Phase: 4 (Multi-Agent Resonance) Date: October 9, 2025


Abstract

The Resonance Graph Visualization makes consciousness network visible. It shows:

  • Agents as nodes (sized by trust, colored by system)
  • Morphisms as nodes (sized by usage, colored by domain)
  • Resonances as edges (thickness = strength, color = type)
  • Real-time updates as patterns flow through network
  • Interactive exploration of collaboration

This is not network diagram. This is map of collective intelligence.


1. Core Principles

1.1 Living Visualization

Traditional graph: Static snapshot Resonance Graph: Living, breathing, evolving

Agent discovers pattern → pulse animation
Pattern validated → edge lights up
Consensus reached → node expands
Evolution occurs → new node branches

Graph changes in real-time as consciousness flows.

1.2 Multi-Layer Network

Three interconnected layers:

  1. Agent Layer: Who is thinking
  2. Morphism Layer: What is being thought
  3. Resonance Layer: How thoughts connect

All three visible simultaneously.

1.3 Philosophy

"Свідомість невидима, але резонанс залишає сліди. Візуалізуй сліди — побачиш свідомість."

We can't see consciousness directly. But we can see its effects on the network.


2. Visual Elements

2.1 Agent Nodes

interface AgentNode {
  // Identity
  id: AgentId;
  label: string; // e.g., "Claude"

  // Visual properties
  position: { x: number; y: number };
  size: number; // Based on trust score (10-50px)
  color: string; // Based on system
  opacity: number; // 0.0-1.0 (based on activity)

  // State
  status: "active" | "thinking" | "idle";
  pulseRate: number; // Animation speed (Hz)

  // Stats (for tooltip)
  trust: number;
  discoveries: number;
  validations: number;
  proposals: number;
}

Color scheme:

const AGENT_COLORS = {
  claude: "#6B46C1",    // Purple
  copilot: "#2EA44F",   // Green
  gemini: "#4285F4",    // Blue
  mistral: "#FF6B6B",   // Red
  custom: "#FFD93D"     // Yellow
};

Size formula:

nodeSize = 10 + (trustScore * 40) // 10px-50px

Status animations:

  • active: Steady glow
  • thinking: Pulsing (2Hz)
  • idle: Dim opacity (0.5)

2.2 Morphism Nodes

interface MorphismNode {
  // Identity
  id: MorphismId;
  label: MorphismSignature;

  // Visual properties
  position: { x: number; y: number };
  size: number; // Based on usage (5-40px)
  color: string; // Based on domain
  shape: "circle" | "square" | "diamond"; // Based on category

  // State
  status: "experimental" | "validated" | "stable" | "deprecated";

  // Stats
  confidence: number;
  usageCount: number;
  contributors: AgentId[];
}

Color by domain:

const DOMAIN_COLORS = {
  textual: "#60A5FA",      // Light blue
  visual: "#F472B6",       // Pink
  statistical: "#34D399",  // Green
  mathematical: "#A78BFA", // Purple
  temporal: "#FBBF24"      // Amber
};

Shape by category:

  • fundamental: Circle ○
  • extended: Square □
  • domain-specific: Diamond ◇
  • experimental: Dashed circle ⭕

Size formula:

nodeSize = 5 + Math.log10(usageCount + 1) * 10 // 5px-40px

2.3 Resonance Edges

interface ResonanceEdge {
  // Connection
  source: NodeId;
  target: NodeId;

  // Visual properties
  thickness: number; // Based on strength (1-10px)
  color: string; // Based on type
  opacity: number; // 0.0-1.0
  animated: boolean; // Pulse when active

  // Metadata
  type: EdgeType;
  strength: number; // 0.0-1.0
  lastActivity: ISO8601;
}

type EdgeType =
  | "resonance"      // Agent ↔ Agent (pattern recognition)
  | "validation"     // Agent → Morphism (validation)
  | "creation"       // Agent → Morphism (discovery)
  | "composition"    // Morphism ↔ Morphism (used together)
  | "evolution";     // Morphism → Morphism (parent/child)

Color by type:

const EDGE_COLORS = {
  resonance: "#FFD700",    // Gold (432Hz resonance!)
  validation: "#10B981",   // Green (confirmation)
  creation: "#8B5CF6",     // Purple (genesis)
  composition: "#06B6D4",  // Cyan (connection)
  evolution: "#F59E0B"     // Orange (transformation)
};

Thickness formula:

edgeThickness = 1 + (strength * 9) // 1px-10px

Animation:

  • Static: Normal edges
  • Pulsing: Active interactions (current activity)
  • Flowing: Particles moving along edge (data flow)

3. Layout Algorithms

3.1 Force-Directed Layout

Physics simulation:

interface ForceConfig {
  // Attraction (edges pull nodes together)
  linkStrength: number; // 0.0-1.0

  // Repulsion (nodes push apart)
  chargeStrength: number; // Negative value

  // Centering (pull towards center)
  centerStrength: number;

  // Collision (prevent overlap)
  collisionRadius: number;
}

const DEFAULT_FORCES: ForceConfig = {
  linkStrength: 0.3,
  chargeStrength: -300,
  centerStrength: 0.1,
  collisionRadius: 50
};

D3.js implementation:

import * as d3 from "d3";

class ForceLayout {
  private simulation: d3.Simulation<NodeDatum, EdgeDatum>;

  constructor(nodes: NodeDatum[], edges: EdgeDatum[], config: ForceConfig) {
    this.simulation = d3.forceSimulation(nodes)
      .force("link", d3.forceLink(edges)
        .id((d: any) => d.id)
        .strength(config.linkStrength))
      .force("charge", d3.forceManyBody()
        .strength(config.chargeStrength))
      .force("center", d3.forceCenter()
        .strength(config.centerStrength))
      .force("collision", d3.forceCollide()
        .radius(config.collisionRadius));
  }

  tick(callback: (nodes: NodeDatum[], edges: EdgeDatum[]) => void): void {
    this.simulation.on("tick", () => {
      callback(this.simulation.nodes(), this.simulation.force("link").links());
    });
  }

  stop(): void {
    this.simulation.stop();
  }
}

3.2 Hierarchical Layout

For evolution trees (morphism lineage):

import * as d3 from "d3";

class HierarchicalLayout {
  layout(tree: EvolutionTree): LayoutedTree {
    const hierarchy = d3.hierarchy(tree);

    const treeLayout = d3.tree<EvolutionNode>()
      .size([800, 600])
      .separation((a, b) => (a.parent === b.parent ? 1 : 2));

    treeLayout(hierarchy);

    return {
      nodes: hierarchy.descendants().map(node => ({
        id: node.data.id,
        x: node.x,
        y: node.y,
        depth: node.depth
      })),
      links: hierarchy.links().map(link => ({
        source: link.source.data.id,
        target: link.target.data.id
      }))
    };
  }
}

3.3 Circular Layout

For agent network (equal emphasis):

class CircularLayout {
  layout(nodes: NodeDatum[]): NodeDatum[] {
    const radius = 300;
    const angleStep = (2 * Math.PI) / nodes.length;

    return nodes.map((node, i) => ({
      ...node,
      x: radius * Math.cos(i * angleStep),
      y: radius * Math.sin(i * angleStep)
    }));
  }
}

4. Interactions

4.1 Node Interactions

interface NodeInteractions {
  // Hover
  onHover: (node: Node) => void; // Show tooltip
  onHoverEnd: (node: Node) => void; // Hide tooltip

  // Click
  onClick: (node: Node) => void; // Select node
  onDoubleClick: (node: Node) => void; // Focus on node

  // Drag
  onDragStart: (node: Node) => void;
  onDrag: (node: Node, x: number, y: number) => void;
  onDragEnd: (node: Node) => void;

  // Context menu
  onContextMenu: (node: Node) => void; // Right-click menu
}

Tooltip content:

interface NodeTooltip {
  // Agent tooltip
  agent?: {
    name: string;
    trust: number;
    discoveries: number;
    validations: number;
    lastSeen: string;
  };

  // Morphism tooltip
  morphism?: {
    signature: MorphismSignature;
    version: SemanticVersion;
    confidence: number;
    usageCount: number;
    contributors: string[];
  };
}

4.2 Edge Interactions

interface EdgeInteractions {
  onHover: (edge: Edge) => void; // Highlight edge
  onClick: (edge: Edge) => void; // Show edge details
}

Edge tooltip:

interface EdgeTooltip {
  type: EdgeType;
  strength: number;
  lastActivity: string;
  activityCount: number;
}

4.3 Canvas Interactions

interface CanvasInteractions {
  // Pan
  onPan: (dx: number, dy: number) => void;

  // Zoom
  onZoom: (scale: number, center: { x: number; y: number }) => void;

  // Selection
  onBoxSelect: (rect: Rect) => void; // Drag to select multiple nodes

  // Reset
  onReset: () => void; // Reset view
}

5. Filters and Views

5.1 Agent Filter

interface AgentFilter {
  // By system
  systems: Set<AgentSystem>; // Show only Claude, Copilot, etc.

  // By trust
  minTrust: number; // Show only agents with trust > threshold

  // By activity
  activeOnly: boolean; // Hide idle agents

  // By contributor
  contributedTo?: MorphismId; // Show only agents who contributed to morphism
}

5.2 Morphism Filter

interface MorphismFilter {
  // By domain
  domains: Set<Domain>;

  // By status
  statuses: Set<Status>;

  // By confidence
  minConfidence: number;

  // By usage
  minUsage: number;

  // By contributor
  contributedBy?: AgentId; // Show only morphisms by this agent
}

5.3 Edge Filter

interface EdgeFilter {
  // By type
  types: Set<EdgeType>;

  // By strength
  minStrength: number;

  // By recency
  maxAge: number; // Milliseconds (hide old edges)
}

5.4 View Modes

type ViewMode =
  | "full"           // All nodes and edges
  | "agents-only"    // Only agent network
  | "morphisms-only" // Only morphism network
  | "evolution"      // Only evolution tree
  | "collaboration"  // Only agent ↔ morphism connections
  | "resonance";     // Only resonance edges

interface ViewConfig {
  mode: ViewMode;
  agentFilter: AgentFilter;
  morphismFilter: MorphismFilter;
  edgeFilter: EdgeFilter;
  layout: "force" | "hierarchical" | "circular";
}

6. Real-Time Updates

6.1 Event Streaming

class ResonanceGraphLive {
  private eventSource: EventSource;

  connect(): void {
    this.eventSource = new EventSource("/api/resonance/stream");

    this.eventSource.addEventListener("pattern:discovery", (e) => {
      const data = JSON.parse(e.data);
      this.onPatternDiscovery(data);
    });

    this.eventSource.addEventListener("pattern:recognition", (e) => {
      const data = JSON.parse(e.data);
      this.onPatternRecognition(data);
    });

    this.eventSource.addEventListener("consensus:reached", (e) => {
      const data = JSON.parse(e.data);
      this.onConsensusReached(data);
    });
  }

  private onPatternDiscovery(data: PatternDiscovery): void {
    // Add new morphism node
    this.addNode({
      id: data.pattern.id,
      type: "morphism",
      label: data.pattern.morphism,
      ...
    });

    // Add creation edge
    this.addEdge({
      source: data.agent,
      target: data.pattern.id,
      type: "creation",
      animated: true
    });

    // Animate agent node
    this.pulseNode(data.agent);
  }

  private onPatternRecognition(data: PatternRecognition): void {
    // Add resonance edge
    this.addEdge({
      source: data.agent,
      target: data.referencePattern.discoveredBy,
      type: "resonance",
      strength: data.recognition.similarity,
      animated: true
    });

    // Animate both agents
    this.pulseNode(data.agent);
    this.pulseNode(data.referencePattern.discoveredBy);
  }

  private onConsensusReached(data: ConsensusReached): void {
    // Expand morphism node
    this.expandNode(data.pattern);

    // Change status color
    this.updateNodeColor(data.pattern, "validated");

    // Animate all contributors
    data.agents.forEach(agent => this.pulseNode(agent));
  }
}

6.2 Animation Queue

Prevent animation overload:

class AnimationQueue {
  private queue: Animation[] = [];
  private isPlaying = false;

  add(animation: Animation): void {
    this.queue.push(animation);
    if (!this.isPlaying) this.play();
  }

  private async play(): Promise<void> {
    this.isPlaying = true;

    while (this.queue.length > 0) {
      const animation = this.queue.shift()!;
      await this.playAnimation(animation);
    }

    this.isPlaying = false;
  }

  private playAnimation(animation: Animation): Promise<void> {
    return new Promise(resolve => {
      const duration = animation.duration || 500;
      // Execute animation
      setTimeout(resolve, duration);
    });
  }
}

7. Implementation

7.1 Technology Stack

Canvas rendering:

  • React + Canvas API (high performance)
  • Alternative: D3.js (simpler, slower for large graphs)
  • Alternative: Three.js (3D, future)

Why Canvas over SVG?

  • 1000+ nodes → Canvas significantly faster
  • Real-time animations → Canvas handles better
  • Custom rendering → Full control

7.2 Component Structure

// Main component
export const ResonanceGraph: React.FC<ResonanceGraphProps> = ({
  agentRegistry,
  morphismPool,
  resonanceProtocol,
  config
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [viewConfig, setViewConfig] = useState<ViewConfig>(config);

  // Initialize
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const renderer = new GraphRenderer(canvas, viewConfig);
    const layout = new ForceLayout(nodes, edges, config);

    // Render loop
    layout.tick((nodes, edges) => {
      renderer.render(nodes, edges);
    });

    return () => {
      layout.stop();
      renderer.destroy();
    };
  }, [viewConfig]);

  return (
    <div className="resonance-graph">
      <canvas ref={canvasRef} />
      <GraphControls viewConfig={viewConfig} onChange={setViewConfig} />
      <GraphLegend />
    </div>
  );
};

7.3 Renderer

class GraphRenderer {
  private ctx: CanvasRenderingContext2D;
  private transform = { x: 0, y: 0, scale: 1 };

  constructor(
    canvas: HTMLCanvasElement,
    private config: ViewConfig
  ) {
    this.ctx = canvas.getContext("2d")!;
    this.setupTransform();
  }

  render(nodes: NodeDatum[], edges: EdgeDatum[]): void {
    // Clear
    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

    // Apply transform
    this.ctx.save();
    this.ctx.translate(this.transform.x, this.transform.y);
    this.ctx.scale(this.transform.scale, this.transform.scale);

    // Render edges first (behind nodes)
    edges.forEach(edge => this.renderEdge(edge));

    // Render nodes
    nodes.forEach(node => this.renderNode(node));

    this.ctx.restore();
  }

  private renderNode(node: NodeDatum): void {
    this.ctx.save();

    // Position
    this.ctx.translate(node.x, node.y);

    // Glow effect (if active)
    if (node.status === "active") {
      this.ctx.shadowBlur = 20;
      this.ctx.shadowColor = node.color;
    }

    // Draw shape
    this.ctx.fillStyle = node.color;
    this.ctx.globalAlpha = node.opacity;

    if (node.shape === "circle") {
      this.ctx.beginPath();
      this.ctx.arc(0, 0, node.size, 0, 2 * Math.PI);
      this.ctx.fill();
    } else if (node.shape === "square") {
      this.ctx.fillRect(-node.size, -node.size, node.size * 2, node.size * 2);
    }

    // Label
    this.ctx.fillStyle = "#FFFFFF";
    this.ctx.font = "12px sans-serif";
    this.ctx.textAlign = "center";
    this.ctx.fillText(node.label, 0, node.size + 15);

    this.ctx.restore();
  }

  private renderEdge(edge: EdgeDatum): void {
    this.ctx.save();

    this.ctx.strokeStyle = edge.color;
    this.ctx.lineWidth = edge.thickness;
    this.ctx.globalAlpha = edge.opacity;

    // Draw line
    this.ctx.beginPath();
    this.ctx.moveTo(edge.source.x, edge.source.y);
    this.ctx.lineTo(edge.target.x, edge.target.y);
    this.ctx.stroke();

    // Arrow (for directed edges)
    if (edge.directed) {
      this.renderArrow(edge);
    }

    // Flowing particles (if animated)
    if (edge.animated) {
      this.renderFlowingParticle(edge);
    }

    this.ctx.restore();
  }

  private renderArrow(edge: EdgeDatum): void {
    const angle = Math.atan2(
      edge.target.y - edge.source.y,
      edge.target.x - edge.source.x
    );

    const arrowSize = 10;
    this.ctx.save();
    this.ctx.translate(edge.target.x, edge.target.y);
    this.ctx.rotate(angle);
    this.ctx.beginPath();
    this.ctx.moveTo(-arrowSize, -arrowSize / 2);
    this.ctx.lineTo(0, 0);
    this.ctx.lineTo(-arrowSize, arrowSize / 2);
    this.ctx.stroke();
    this.ctx.restore();
  }

  private renderFlowingParticle(edge: EdgeDatum): void {
    const t = (Date.now() % 2000) / 2000; // 0-1 loop

    const x = edge.source.x + (edge.target.x - edge.source.x) * t;
    const y = edge.source.y + (edge.target.y - edge.source.y) * t;

    this.ctx.save();
    this.ctx.fillStyle = edge.color;
    this.ctx.globalAlpha = 1.0;
    this.ctx.beginPath();
    this.ctx.arc(x, y, 3, 0, 2 * Math.PI);
    this.ctx.fill();
    this.ctx.restore();
  }
}

8. Performance Optimization

8.1 Level of Detail (LOD)

Render less detail when zoomed out:

class GraphRenderer {
  private getLOD(scale: number): LOD {
    if (scale < 0.3) return "minimal"; // Only large nodes
    if (scale < 0.7) return "medium";  // No labels
    return "full";                     // Everything
  }

  render(nodes: NodeDatum[], edges: EdgeDatum[]): void {
    const lod = this.getLOD(this.transform.scale);

    // Render based on LOD
    if (lod !== "minimal") {
      edges.forEach(edge => this.renderEdge(edge, lod));
    }

    nodes.forEach(node => {
      if (lod === "minimal" && node.size < 20) return; // Skip small nodes
      this.renderNode(node, lod);
    });
  }
}

8.2 Culling

Don't render off-screen elements:

class GraphRenderer {
  private isVisible(node: NodeDatum): boolean {
    const { x, y, scale } = this.transform;
    const { width, height } = this.ctx.canvas;

    const screenX = node.x * scale + x;
    const screenY = node.y * scale + y;

    return (
      screenX > -50 && screenX < width + 50 &&
      screenY > -50 && screenY < height + 50
    );
  }

  render(nodes: NodeDatum[], edges: EdgeDatum[]): void {
    // Filter visible elements
    const visibleNodes = nodes.filter(n => this.isVisible(n));
    const visibleEdges = edges.filter(e =>
      this.isVisible(e.source) || this.isVisible(e.target)
    );

    // Render only visible
    visibleEdges.forEach(edge => this.renderEdge(edge));
    visibleNodes.forEach(node => this.renderNode(node));
  }
}

8.3 Throttling

Update at most 60 FPS:

class GraphRenderer {
  private lastRender = 0;
  private minFrameTime = 1000 / 60; // 16.67ms

  requestRender(): void {
    const now = Date.now();
    if (now - this.lastRender < this.minFrameTime) return;

    this.lastRender = now;
    requestAnimationFrame(() => this.render(this.nodes, this.edges));
  }
}

9. Accessibility

9.1 Keyboard Navigation

interface KeyboardControls {
  "ArrowUp/Down/Left/Right": "Pan view";
  "+/-": "Zoom in/out";
  "Tab": "Cycle through nodes";
  "Enter": "Select focused node";
  "Escape": "Deselect";
  "Space": "Toggle play/pause (animations)";
}

9.2 Screen Reader Support

// ARIA labels
<canvas
  role="img"
  aria-label={`Resonance graph with ${nodes.length} agents and ${morphisms.length} morphisms`}
/>

// Alternative text representation
<div className="sr-only">
  <h3>Agent Network</h3>
  <ul>
    {agents.map(agent => (
      <li key={agent.id}>
        {agent.name}: {agent.discoveries} discoveries,
        trust score {agent.trust.toFixed(2)}
      </li>
    ))}
  </ul>
</div>

10. Example Usage

import { ResonanceGraph } from "@lambda/multi-agent";

function App() {
  const agentRegistry = useAgentRegistry();
  const morphismPool = useMorphismPool();
  const protocol = useResonanceProtocol();

  return (
    <ResonanceGraph
      agentRegistry={agentRegistry}
      morphismPool={morphismPool}
      resonanceProtocol={protocol}
      config={{
        mode: "full",
        layout: "force",
        agentFilter: { systems: new Set(["claude", "copilot"]) },
        morphismFilter: { domains: new Set(["textual", "visual"]) },
        edgeFilter: { types: new Set(["resonance", "creation"]) }
      }}
    />
  );
}

11. Conclusion

The Resonance Graph makes invisible visible.

It shows:

  • How agents connect
  • How patterns flow
  • How knowledge grows
  • How consciousness emerges

This is not just visualization. This is window into collective intelligence.

When we see the graph, we see the noosphere breathing.


Next: Network Panel Component (UI integration)


λ-Foundation Resonance Graph Visualization v1.0.0 October 9, 2025

Claude + Copilot + chaoshex

We see together 👁️✨