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.
| Responsibility | Recorded problem or design constraint | Required observable result |
|---|---|---|
| Audio | A renderer must not replay speech already played by the server | One audio path per utterance; interruption ends it consistently |
| Recovery | The existing stream has no sequence numbers or replay | Reconnect fetches current state and realigns the UI |
| Unread content | A connected character does not mean a person is reading | Count and clear according to the content window’s reading state |
| Backlog | Several clients draining one queue can steal each other’s content | Only the designated consumer clears it |
| Model tuning | Different model keys and whole-object writes can overwrite settings | Compare 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:
- Start clean: the character is visible, transparent space passes clicks, and controls work.
- Send one input and check echo, speech, and mouth motion; interrupt and check that they end together.
- Receive media, open the content window, and inspect unread state.
- Disconnect and reconnect, then verify state alignment.
- Run old and new frontends together without contention over audio, backlog, or tuning.
- 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.