Alias ArchiveArchive in progress
Archive in progress

From Stage to Desktop Companion

Digital Companion Build Journal07 / SERIES

Journal entry seven: separating character rendering from content, input, and state while planning a Unity frontend.

Filed
Field
Other
Edition
EN / Reading copy

This is entry seven in the Digital Companion Build Journal. Earlier entries dealt with memory, speech, and content generation. The next question was whether those capabilities would remain usable after moving into a desktop companion.

This review follows August design and handoff records. A later Unity integration plan superseded the initial desktop migration plan; combining them would invent a final interface neither document describes. Handoff notes confirm some console wiring and fixes, not acceptance of every migration stage.

Receiving a message is not delivering a feature

The August 17 audit found that the desktop frontend received many event types but meaningfully handled only some. Images, video, input echoes, and recording state reached a hidden log region. The connection remained alive and the character moved, but content was invisible in that interface.

“WebSocket connected” can conceal this failure. Delivery must be traced to a visible result, not just to an event handler.

The migration checklist therefore needs user actions: notice a message, open an image, type and send, recognize recording state, interrupt speech, and catch up later. Each must end in something the user can actually observe.

Separate the character from the content window

The first plan placed media cards near the character’s speech bubble. The later Unity plan changed that: the character window would handle presence, motion, and brief notifications, while a separate content window would hold images, video, and history.

This keeps a full application interface from permanently surrounding the character. The content window can support lists, a lightbox, and history without fitting itself around a character silhouette.

Input, microphone controls, the tray, and the console also need explicit entry points. Transparent space should pass clicks to the desktop, while real controls remain clickable. Input needs focus while open and a reliable restoration of the previous behavior when closed. A crash or focus loss must not leave an invisible region blocking the desktop.

These are acceptance behaviors, not automatic consequences of making a window transparent.

Replace rendering without moving every responsibility

The Unity plan replaces the character frontend. Memory, conversation, recognition, speech generation, and content pipelines remain server responsibilities; Electron retains the tray and content UI. The plan also adds a few compatible endpoints and client identity labels. Its “unchanged server” rule is therefore best read as preserving core responsibilities, not literally changing zero lines.

That boundary permits stages: establish rendering and the transparent window, then connect speech, input, notifications, and tuning. Each stage should be reversible without rewriting the whole system.

The old prerendered stage and model-conversion recipes can remain useful as historical assets, mapping references, or fallback paths. A new display frontend does not require immediately deleting them.

Assign consumers before adding more clients

With an old page, character window, and content window open together, the dangerous failures are often duplicated or missing side effects.

ResponsibilityRecorded problem or design constraintRequired observable result
AudioA renderer must not replay speech already played by the serverOne audio path per utterance; interruption ends it consistently
RecoveryThe existing stream has no sequence numbers or replayReconnect fetches current state and realigns the UI
Unread contentA connected character does not mean a person is readingCount and clear according to the content window’s reading state
BacklogSeveral clients draining one queue can steal each other’s contentOnly the designated consumer clears it
Model tuningDifferent model keys and whole-object writes can overwrite settingsCompare keys before writes; separate model namespaces if needed

The August 19 addendum records implementation and testing of server channels for unread state and runtime model structure. Unity reporting, display, and responses still require their corresponding stage checks. An existing endpoint does not establish working client behavior.

Two open windows are consequently not sufficient evidence of success. Disconnect, reconnect, open and close content, and switch models; then inspect whether state was duplicated, lost, or overwritten.

An exported model still needs runtime acceptance

The VRChat-to-VRM workflow records another boundary: producing a file is a format-level outcome. Expressions, blinking, mouth shapes, materials, bones, and secondary motion still need inspection in the actual target runtime.

Use two layers of review. Structural auditing checks references and missing or invalid parameters. Visual and dynamic checks cover the neutral face, expressions, side and rear views, head turns, abrupt stops, raised arms, and recovery to idle. Counts alone are not acceptance criteria.

For a physics problem, do not immediately tune spring parameters. Check visible objects and default deformations, then skinning, rest pose, and constraints, before physics and collision. Otherwise a patch may merely conceal a different fault.

Runtime-specific patches need an explicit boundary too. A fix applied by this desktop application may not exist in the exported asset when another viewer opens it. Native Unity rendering and converted VRM are different routes; physics and material behavior cannot simply be assumed identical.

Turn acceptance into actions

The durable part of these plans is a sequence that can be checked and reversed:

  1. Start clean: the character is visible, transparent space passes clicks, and controls work.
  2. Send one input and check echo, speech, and mouth motion; interrupt and check that they end together.
  3. Receive media, open the content window, and inspect unread state.
  4. Disconnect and reconnect, then verify state alignment.
  5. Run old and new frontends together without contention over audio, backlog, or tuning.
  6. Restore the previous frontend when a stage fails.

The August 21 handoff records a concrete fix: a stop command used a hard-coded action ID and could stall when actions changed. It was corrected to match the actual action. Testing only the first animation would have missed the transition, stop, and recovery paths.

The part worth preserving is this set of responsibilities and checks. It remains useful when deciding whether the next rendering frontend has connected the whole system.

Related reading

03 / LINKS
C01

Building a Digital Companion: A Journal and Reading Map

Two weeks after starting from an open-source desktop companion, the result was a wholly self-owned system. This account also indexes the technical records and a later migration review.

Read post ↗
C02

Treating the Browser as a Display: A Host-Agnostic Stage and Three Infrastructure Battles

An architecture that lets one AI companion inhabit a browser tab, a standalone window, and a desktop wallpaper: move all logic into the server and reduce the page to a display.

Read post ↗
C03

A Selfie System That Chooses Its Own Outfit: Controlled Randomness and Image–Caption Consistency

Designing an AI companion that sends selfies in tune with a conversation: a layered outfit engine, explicit image–caption constraints, restrained proactive sharing, and two image-to-image API failures that returned success while ignoring the reference.

Read post ↗