Switching 姿 makes her disappear #75
Labels
No labels
needs-info
needs-triage
ready-for-agent
ready-for-human
v2
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wayfinder:ticket
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiko/denpa#75
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Reported by the operator on 2026-07-31: "switching models makes them disappear." Observed on the Pixel, against
mainplus the#62–#68batch.Not reproduced under instrumentation.
updateModelConfigis module-scoped rather than a window global, so the switch cannot be driven from DevTools and I could not capture the console for the failing moment. What follows is the path and the most likely mechanism, not a confirmed root cause — whoever takes this should reproduce it first.The path
use-live2d-model.ts's model effect fires whenmodelInfo.urlchanges. It callsupdateModelConfig(...)and then, after 500ms:initializeLive2D(WebSDK/src/main.ts) releases the manager again if a delegate exists, then guards on:Why this is the same family as
#68#68was the same singletons losing their canvas. It was fixed by never unmounting the canvas — the model is now portalled into a host that survives both the mode branch and the onboarding gate.What
#68did not touch is the release-and-reinitialise path, which is the only path that still tears Cubism down deliberately.LAppGlManager.getInstance()returns the existing singleton bound to the original#canvaselement, and onlyLAppLive2DManageris released — the delegate, the GL manager and the view are reused. Ifinitialize()returns false, or returns true against a stale view, the manager reloads the new model into something that no longer draws.The comment left on that timer in
#68's wake says the cleanup stays because "the model url can change under a 姿 switch". That is exactly the case being reported, and it is the one case that was never exercised.What to check first, in order
works.aiko.ollvt.debugis a debug build with webview debugging on:adb forward tcp:9222 localabstract:webview_devtools_remote_<pid>and watch forFailed to initialize Live2Dat the moment of the switch. That one line splits this in two: guard failure versus a silent reuse of a dead view.[CSM][E]Failed to load filein logcat means it is an asset problem rather than a GL one — note#69's sibling, where the model url was resolved against the wrong origin.#68removed for mode switches. If a switch now only ever happens from one place, the delay may be delaying the very re-init the operator is waiting for.Also worth knowing
#52made 姿 offer the go-between's real model register, so switching is now a normal thing to do rather than a developer's edge case.model_dict.jsoncurrently holdsmao_proandxiaozhanglang, so this is reachable in two taps.Acceptance
#68's host isRelated
denpa#68,denpa#52,denpa#69Not reproducible on the desktop from a clean start, on
mainwith#69and#76merged. The operator switched 姿 repeatedly, both directions, and switched window → pet → window before switching again. She stayed drawn every time. Leaving this open rather than closing it: the original report was on the Pixel, against a built APK, and that has not been retested.What the instrumentation established
The issue's premise is wrong in one specific way. It says the release-and-reinitialise path 'is the one case that was never exercised'. It runs on every switch — probes at four points around it (
before release,after init,+1s,+3s) fired on each one, and the model loaded correctly each time:updateModelConfigreceived the rightresourcePath,modelDirectoryandmodelFileName, textures were set up, and the Cubism core reported its version. NoFailed to initialize Live2D, no[CSM][E]Failed to load file. So check 1 and check 2 in 'What to check first' are both answered, negatively.What was found instead
A deterministic trigger for the same mechanism, in dev. Any Fast Refresh of
components/canvas/live2d.tsx— a singlehmr updateline, no page reload — loses her permanently, exactly as described here. Fast Refresh remounts the component, which recreates<canvas id="canvas">.LAppGlManagerbindsdocument.getElementById('canvas')once, into a module-level singleton, and nothing anywhere callsLAppGlManager.releaseInstance(), so Cubism keeps drawing into a canvas React has already discarded. The window is decorationless and transparent, so the result is an invisible window — the same symptom#68opens with.This matters beyond dev: it means
#68's fix is narrower than it reads. The portal stops a mode switch from remounting her; it does not stop the class. Any remount ofLive2Dfrom any cause has this outcome, and the GL manager still has no rebind path.It also means several 'reproductions' earlier today were mine, not the product's. Editing files under a running dev server produced the symptom repeatedly and confounded the first two attempts at this. Anything observed under HMR should be discarded.
What is left
Live2D;#77(she is not drawn in pet mode) may be the same root and is filed separately.Also observed, not this issue
mic already openon every reconnect —vad-context.tsx:512logs it and:524leaves an unhandled promise rejection. It fired on every reconnect during testing. Not filed yet; say the word and it gets a ticket.Moved back to
ready-for-human. The original report was on the Pixel, and the desktop pass on 2026-07-31 could not reproduce it; the acceptance says plainly "verified by switching on a real device, not by reading the path". There is no failing test to derive from here until someone watches it fail again — the next step is a switch on the phone withadb forward tcp:9222 localabstract:webview_devtools_remote_<pid>open, looking forFailed to initialize Live2D. An agent cannot take that step.Closed. The canvas run fixed it:
f334febstops one mistimed attempt deciding the whole session,a7a103fsays whether she is coming or not coming,acb29b5stops watching an absent model at the pace of hope, withaac27aeapplying the default expression to the model being switched to. Verified by the operator.