feat(persona): add Pocket-native parity POC - #3
Conversation
Final visual and performance conclusionThis follow-up replaces the earlier CPU headline with the post-retarget, screenshot-validated result. Visual validity
Final measurements All lanes used Persona
CPU percentages are percentages of one logical core: Stock Persona at full refresh Persona's default React Three Fiber Startup model decoding, moving or clicking the widget, and shader warm-up can briefly read much higher. A 60 Hz display should generally cost less, but the relationship is not guaranteed to be linear and was not inferred as a 60 Hz result here. Interpretation The 30 fps idle result is primarily a user-facing shipping-configuration saving: Pocket delivers about one quarter as many frames and is still 10.6% worse per delivered idle frame. The modular-speaking path and near-refresh-matched lane retain genuine per-frame CPU advantages. Persona-specific policy remains in this repository; PocketJS only gains the generic window-visibility hook (#204) and generic VRMA retarget fix (#207). |
Summary
pocket-character: native host, QuickJS policy, catalog handling, bridge/MCP compatibility, visual acceptance, and fail-closed benchmark toolingbb7ef2455b23aee685f68c9e83a185347d257964(0.1.0-beta.0), including its packaged avatar, idle clip, and 17 modular speaking clips0.7 sresume hold,0.9 stalk-to-idle hold,0.35 sbody transitions, and one-shot return to the underlying voice roleOne-line acceptance
Omit
-- --cycles 1to leave either target running for interactive inspection. Both commands validate and stage the same controlled VRM/VRMA fixture and drive idle → speaking/lip-sync → listening → greeting. Visual acceptance must inspect the whole character, especially shoulder/wrist/hand and hip/knee/ankle/foot axes.Sequential packaged-asset measurements:
The benchmark runs Persona and Pocket sequentially, requires the requested voice state at settle and every sample, validates Pocket animation/amplitude, and fails if Pocket's render frame count does not advance.
Repository boundary
All Persona-specific behavior remains in this repository. PocketJS only receives two generic, independently reviewable capabilities:
This branch pins
vendor/pocketjsto #207 head0341db00a92b9c8a040288a25bd690af7e55fe61. #207 is stacked on #204 and can be retargeted tomainafter #204 lands. Repin this submodule to the final merge SHA(s) before merging this PR.Measured result
MacBook Pro
Mac15,8, Apple M3 Max, macOS26.5.2, 120 Hz display. Each final lane ran sequentially with a 30-second settle and nine 5-second process-tree samples using Persona's clean packaged catalog atbb7ef245….The old 89.5% idle claim is invalid: that run visibly mis-retargeted raw local VRMA rotations, so it did not render the same pose. These are post-fix results paired with actual live Persona screenshots and Pocket idle plus modular-speaking screenshots. The idle absolute CPU win is largely a shipping-configuration win; its per-frame cost is still 10.6% worse. Speaking and the near-refresh-matched lane retain per-frame CPU advantages.
Validation
bun run typecheckbun test tests/persona-bench.test.ts— 5 tests, 13 assertionscargo test -p pocket-persona— 23 passedcargo clippy -p pocket-persona --all-targets -- -D warningscargo check --workspace --all-targetspocket-vrm: 19 unit + 6 fixture tests passed; Clippy and targeted rustfmt check passedbun run accept:persona -- --cycles 1bun run accept:pocket -- --cycles 1status: "ok"status: "ok"and advanced PocketrenderFrameCountfrom 23 to 54 during its sampling window--headless-speakingsequence plus idle/reference captures; hands and feet remain fully framed with natural joint axesNotes
public/assets/LICENSES.md.