Back to Publiclear

Publiclear Simulation Studio Implementation Spec

Single handoff document for frontend, backend, and realtime infrastructure. Covers screen flow, data contracts, streaming events, and acceptance tests.

Updated: February 22, 2026 (Asia/Kolkata)

OpenAPI Contracts TypeScript Interfaces Realtime Streaming Acceptance Tests

0) Spec Index

  1. Product Architecture
  2. Screen Map and Route Flow
  3. Ingestion State Machine
  4. Personality Calibration Schema
  5. Voice Training Contract
  6. Avatar Generation Contract
  7. Core REST API Endpoints
  8. OpenAPI Snippets
  9. TypeScript Shared Interfaces
  10. Realtime Streaming Events
  11. Frontend Realtime Handling Rules
  12. Acceptance Test Matrix
  13. Performance and SLO Targets
  14. Security and Compliance Controls

1) Product Architecture

Frontend

  • React + TypeScript SPA.
  • Zustand or equivalent store for multi-step studio state.
  • WebRTC/WebSocket realtime transport.
  • UI modules: Demo, Studio, Portal, Admin/Owner controls.

Backend

  • API service for CRUD and auth.
  • Worker queue for ingestion and model jobs.
  • Vector database for memory retrieval.
  • Object storage for audio/photo/docs.

Core Services

2) Screen Map and Route Flow

Screen Route Goal Primary UI API Calls Done Condition
S0 /studio/new Create workspace Name, language, consent checkbox POST /v1/simulations simulation_id exists
S1 /studio/:id/ingest Add source memories Upload queue, stage progress, retry POST /v1/uploads/presign, POST /v1/simulations/:id/ingestions, GET /v1/jobs/:job_id/events At least one ingestion complete
S2 /studio/:id/personality Calibrate personality Sliders, values, catchphrases, taboo topics PUT /v1/simulations/:id/persona Persona validation pass
S3 /studio/:id/relationships Relationship behavior map Relation cards and tone overrides PUT /v1/simulations/:id/relationships One relation profile created
S4 /studio/:id/voice Train voice model Recorder, noise checks, segment quality report POST /v1/simulations/:id/voice/samples, POST /v1/simulations/:id/voice/train Voice status ready
S5 /studio/:id/avatar Generate avatar Photo upload, quality checks, preview POST /v1/simulations/:id/avatar/upload, POST /v1/simulations/:id/avatar/render Avatar status ready
S6 /studio/:id/preview End-to-end test Realtime chat + avatar + timeline POST /v1/realtime/sessions Audio, text, viseme streams healthy
S7 /studio/:id/publish Go live Access rules, share link, slug setup POST /v1/simulations/:id/publish, POST /v1/simulations/:id/access-links Portal link active
S8 /portal/:slug Family usage Avatar call, chat transcript, memory timeline POST /v1/realtime/sessions, POST /v1/conversations/:id/turns Stable session and persisted transcript

3) Ingestion State Machine

{
  "states": [
    "idle",
    "uploading",
    "queued",
    "extracting_text",
    "chunking",
    "embedding",
    "indexing",
    "complete",
    "failed"
  ],
  "metrics": {
    "progress_pct": "number",
    "chunks_done": "number",
    "chunks_total": "number",
    "token_count": "number"
  }
}

UI Rules During Ingestion

4) Personality Calibration Schema

{
  "display_name": "string (2-80)",
  "primary_language": "en-IN | hi-IN | ...",
  "secondary_languages": ["string"],
  "speech_style": {
    "warmth": 0,
    "humor": 0,
    "formality": 0,
    "directness": 0,
    "spirituality": 0
  },
  "catchphrases": ["string"],
  "core_values_ranked": ["family", "discipline", "kindness"],
  "taboo_topics": ["string"],
  "favorite_topics": ["string"],
  "memory_cards": [
    {
      "year": 1983,
      "title": "World Cup memory",
      "people": ["brother", "neighbors"],
      "context": "street radio listening",
      "tone": "joyful"
    }
  ]
}

5) Voice Training Contract

Validation Requirements

  • Total voiced duration: at least 120 seconds.
  • Segment duration: 8 to 25 seconds each.
  • Sample rate: at least 16kHz.
  • SNR: at least 18dB.
  • Silence ratio: less than 35%.
  • Single speaker confidence: at least 0.85.

Quality Failure Example

{
  "status": "quality_failed",
  "report": {
    "snr_db": 13.2,
    "clipping_pct": 0.4,
    "silence_pct": 42.1,
    "single_speaker_confidence": 0.91
  },
  "issues": [
    {"code": "LOW_SNR", "message": "Move to quieter room"},
    {"code": "TOO_MUCH_SILENCE", "message": "Speak continuously"}
  ]
}

6) Avatar Upload Contract

{
  "status": "accepted",
  "quality_report": {
    "face_count": 1,
    "occlusion_score": 0.08,
    "yaw_deg": 6.1,
    "pitch_deg": 4.2,
    "lighting_score": 0.82
  }
}

7) REST API Endpoints

Method Path Purpose Auth
POST/v1/simulationsCreate simulation workspaceBearer
GET/v1/simulations/:idRead workspace metadataBearer
POST/v1/uploads/presignCreate upload URLBearer
POST/v1/simulations/:id/ingestionsStart ingestion jobBearer
GET/v1/jobs/:job_id/eventsStream job progressBearer
PUT/v1/simulations/:id/personaSave personality configBearer
PUT/v1/simulations/:id/relationshipsSave relationship mapsBearer
POST/v1/simulations/:id/voice/samplesRegister voice segmentsBearer
POST/v1/simulations/:id/voice/trainStart voice trainingBearer
POST/v1/simulations/:id/avatar/uploadUpload avatar source imageBearer
POST/v1/simulations/:id/avatar/renderStart avatar render jobBearer
POST/v1/realtime/sessionsCreate realtime session tokenBearer
POST/v1/simulations/:id/publishPublish simulation portalBearer
POST/v1/simulations/:id/access-linksCreate family share linksBearer
POST/v1/conversations/:id/turnsPersist chat turnsBearer

8) OpenAPI Snippets (YAML)

openapi: 3.1.0
info:
  title: Publiclear API
  version: 1.0.0
paths:
  /v1/simulations:
    post:
      summary: Create simulation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSimulationRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Simulation'
  /v1/realtime/sessions:
    post:
      summary: Create realtime session
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RealtimeSessionRequest'
      responses:
        '200':
          description: Session token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RealtimeSession'
components:
  schemas:
    CreateSimulationRequest:
      type: object
      required: [name, primary_language, consent]
      properties:
        name: {type: string, minLength: 2, maxLength: 80}
        primary_language: {type: string}
        consent: {type: boolean}
    Simulation:
      type: object
      properties:
        simulation_id: {type: string}
        owner_id: {type: string}
        status: {type: string}
    RealtimeSessionRequest:
      type: object
      required: [simulation_id, relationship_id]
      properties:
        simulation_id: {type: string}
        relationship_id: {type: string}
        mode: {type: string, enum: [audio, text, multimodal]}
    RealtimeSession:
      type: object
      properties:
        session_id: {type: string}
        token: {type: string}
        expires_at: {type: string, format: date-time}

9) TypeScript Shared Interfaces

export interface Simulation {
  simulation_id: string;
  owner_id: string;
  name: string;
  primary_language: string;
  status: "draft" | "ready" | "published";
  created_at: string;
  updated_at: string;
}

export interface IngestionItem {
  ingestion_id: string;
  simulation_id: string;
  source_type: "file" | "whatsapp" | "manual" | "email_export";
  stage:
    | "idle"
    | "uploading"
    | "queued"
    | "extracting_text"
    | "chunking"
    | "embedding"
    | "indexing"
    | "complete"
    | "failed";
  progress_pct: number;
  chunks_done: number;
  chunks_total: number;
  token_count: number;
  error_code?: string;
  error_message?: string;
}

export interface RelationshipProfile {
  person_id: string;
  name: string;
  relation: string;
  closeness: 1 | 2 | 3 | 4 | 5;
  address_style: string;
  inside_jokes: string[];
  avoid_topics: string[];
  response_tone_override?: {
    warmth?: number;
    formality?: number;
    humor?: number;
    directness?: number;
  };
}

export interface TurnRequest {
  session_id: string;
  simulation_id: string;
  relationship_id: string;
  input: {
    modality: "audio" | "text";
    text?: string;
    language: string;
    audio_ref?: string;
  };
  options: {
    stream: boolean;
    temperature: number;
    max_output_tokens: number;
  };
}

export interface TurnResponse {
  turn_id: string;
  output_text: string;
  memory_citations: string[];
  latency_ms: {
    retrieval: number;
    first_token: number;
    total: number;
  };
}

10) Realtime Streaming Events

Event Types

{
  "type": "response.output_text.delta",
  "turn_id": "turn_001",
  "seq": 12,
  "delta": "In school, we loved",
  "timestamp": "2026-02-22T10:15:17.311Z"
}
{
  "type": "avatar.viseme.delta",
  "turn_id": "turn_001",
  "seq": 12,
  "audio_offset_ms": 1640,
  "visemes": [
    {"t_ms": 0, "v": "AA", "w": 0.7},
    {"t_ms": 90, "v": "M", "w": 0.6},
    {"t_ms": 170, "v": "EH", "w": 0.8}
  ]
}

11) Frontend Realtime Handling Rules

12) Acceptance Test Matrix

Area Test Case Expected Result
S0 CreateCreate simulation with consent uncheckedSubmit blocked with inline validation
S1 IngestionUpload mixed files (pdf, txt, invalid)Valid files proceed, invalid file shows actionable error
S1 IngestionInterrupt network during embeddingProgress resumes or retry starts from last persisted checkpoint
S2 PersonaSave with missing required slidersField-level errors and save prevented
S3 RelationshipsAdd tone override for one relationshipOverride reflected in preview responses
S4 VoiceAudio with high noiseQuality fail with exact issue codes and recapture guidance
S5 AvatarUpload photo with two facesRejected with multi-face error and guidance
S6 PreviewRun multimodal turnText delta, audio delta, viseme delta all stream successfully
S7 PublishCreate share link with expiryLink generated, expiry enforced server-side
S8 PortalConcurrent family sessionsNo cross-session memory leakage

13) Performance and SLO Targets

14) Security and Compliance Controls