ENGINEERING DOCS

v1.0.4-alpha / Protocol Specifications

1. Semantic Buffer AST

The Semantic Buffer is a stateful tree that receives intention-based nodes from the Voice-to-JSON stream. Unlike raw LLM outputs (which frequently hallucinate unstructured JSON), this component guarantees structural type safety before execution via the Figma MCP.

Schema definition: BufferNode (TypeScript)

interface BufferNode {
  id: string;               // UUID-v4
  type: ElementType;        // 'FRAME' | 'TEXT' | 'BUTTON' | 'INPUT'
  intent: string;           // Original JEV transcript snippet
  properties: {
    layout: 'FLEX' | 'GRID' | 'ABSOLUTE';
    direction?: 'HORIZONTAL' | 'VERTICAL';
    padding?: [number, number, number, number];
    gap?: number;
    fill?: HexColor | 'TRANSPARENT';
    stroke?: HexColor;
    cornerRadius?: number;
  };
  children: BufferNode[];
  _mcp_ref?: string;        // Native Figma node ID after MCP realization
}

2. Voice Streaming Protocol

Voice streams are chunked via WebRTC and piped to the JEV endpoint. Partial transcripts are eagerly resolved into diffs against the Semantic Buffer to provide real-time UI feedback while the user is still speaking.

Terminal trace: WebSocket Engine (Port 8080)

[15:42:01.102] INFO: ws_connect client=v_designer_99
< AUDIO_CHUNK [4096 bytes]
< AUDIO_CHUNK [4096 bytes]
> PARTIAL_JSON: {"transcript": "add a red button", "confidence": 0.89}
< AUDIO_CHUNK [4096 bytes]
> COMMIT_JSON: {"transcript": "add a red button that says submit", "intent_parsed": true}
* BUFFER_DIFF: +Node(type=BUTTON, fill=#FF0000, text="Submit")

3. Figma MCP Operations

The MCP server polls the Semantic Buffer and executes atomic design operations via Figma's native Plugin API. By maintaining the _mcp_ref, future edits target existing nodes rather than re-generating elements from scratch.

operation.ts
async function executeMcpCommand(node: BufferNode) {
  if (node._mcp_ref) {
    // Node exists, apply mutation (progressive editing)
    const figmaNode = await figma.getNodeByIdAsync(node._mcp_ref);
    if (figmaNode && figmaNode.type === 'FRAME') {
      figmaNode.fills = [{ type: 'SOLID', color: hexToFigmaRgb(node.properties.fill) }];
    }
    return;
  }

  // Create new native Figma node
  const frame = figma.createFrame();
  frame.name = `${node.type}_${node.id.substring(0, 4)}`;
  
  // Apply Auto-Layout semantics
  if (node.properties.layout === 'FLEX') {
    frame.layoutMode = node.properties.direction || 'HORIZONTAL';
    frame.itemSpacing = node.properties.gap || 0;
  }
  
  // Persist reference back to buffer for future modifications
  node._mcp_ref = frame.id;
  figma.currentPage.appendChild(frame);
}