## Title `sprimo-tauri` runtime shows `TypeError: W.fromURL is not a function`; sprite renderer fails to initialize. ## Severity P1 ## Environment - OS: Windows - App: `sprimo-tauri` frontend/runtime path - Reported on: 2026-02-13 - Evidence screenshot: `issues/screenshots/issue2.png` ## Summary At runtime, the Tauri UI loads but Pixi sprite rendering fails with: - `TypeError: W.fromURL is not a function` This breaks sprite presentation and leaves the UI in an error state. ## Reproduction Steps 1. Build UI assets and start the Tauri app (`just build-tauri-ui`, `just run-tauri`). 2. Open the Tauri window and wait for sprite pack initialization. 3. Observe the debug panel error and missing pet rendering. ## Expected Result - Pixi atlas texture loads successfully from `atlas_data_url`. - Pet sprite renders and animates. - No renderer initialization error in UI. ## Actual Result - Renderer initialization fails with `TypeError: W.fromURL is not a function`. - Sprite is not rendered. ## Root Cause Analysis - `frontend/tauri-ui/src/renderer/pixi_pet.ts` used `BaseTexture.fromURL(...)`. - In the current Pixi package/runtime composition, that API path is unavailable at runtime (minified symbol resolves to `W.fromURL`, which is undefined). - Result: atlas load throws before a valid sprite texture can be applied. - Follow-up finding: Tauri can run previously embedded frontend assets if Rust build is not re-triggered after UI-only changes, which can make old errors appear even after source fixes. - After stale-build issue was resolved (`ui build: issue2-fix3` visible), a second runtime defect became clear: - `event.listen not allowed` due missing Tauri capability permissions for event listen/unlisten. - sprite pack still rendered with magenta matte because tauri path lacked chroma-key conversion. ## Fix Plan 1. Replace `BaseTexture.fromURL` usage with Pixi assets loader (`@pixi/assets` + `Assets.load`). 2. Ensure sprite texture is assigned immediately after renderer creation (first frame visible). 3. Harden React lifecycle cleanup to avoid stale listeners/renderer leaks. 4. Re-run tauri/runtime QA checks and keep issue at `Fix Implemented` until strict gate evidence is complete. ## Implementation Notes Implemented: 1. `frontend/tauri-ui/package.json` - Added `@pixi/assets` dependency. 2. `frontend/tauri-ui/src/renderer/pixi_pet.ts` - Switched atlas loading to `Assets.load(pack.atlas_data_url)`. - Reused `texture.baseTexture` for frame slicing. - Applied initial frame texture in constructor so sprite appears immediately. - Added explicit renderer/sprite/ticker disposal path. 3. `frontend/tauri-ui/src/main.tsx` - Added mount guards to prevent state updates after unmount. - Added deterministic cleanup (`unlisten` + renderer `dispose()`). 4. `crates/sprimo-tauri/build.rs` - Added `cargo:rerun-if-changed` directives for tauri config and frontend UI paths so frontend/dist updates re-trigger asset embedding in `cargo run -p sprimo-tauri`. 5. `frontend/tauri-ui/src/renderer/pixi_pet.ts` - Replaced `Assets.load` path with direct `Image` + `BaseTexture.from(image)` loading to avoid any runtime `*.fromURL` dependency in atlas initialization. 6. `frontend/tauri-ui/src/main.tsx` - Added visible UI build marker (`issue2-fix3`) to detect stale embedded frontend artifacts. 7. `crates/sprimo-tauri/capabilities/default.json` - Added default capability with: - `core:default` - `core:event:allow-listen` - `core:event:allow-unlisten` 8. `frontend/tauri-ui/src/renderer/pixi_pet.ts` - Added tauri-side chroma-key conversion for atlas data URL: - draw atlas to canvas - convert near-`#FF00FF` pixels to alpha 0 - create Pixi base texture from converted canvas ## Verification ### Commands Run - [x] `cargo check -p sprimo-tauri` - [x] `cargo check -p sprimo-runtime-core` - [x] `just build-tauri-ui` - [x] `just run-tauri` (smoke attempt; command is long-running and timed out under automation) - [x] `just qa-validate` ### Visual Checklist - [x] Before screenshot(s): `issues/screenshots/issue2.png` - [x] After screenshot(s): `issues/screenshots/issue2-after-fix3-2026-02-13-094131.png` ### Runtime Contract Checklist - [ ] `current_state` invoke returns structured payload - [ ] `load_active_sprite_pack` invoke returns manifest/atlas payload - [ ] `runtime:snapshot` event observed after runtime command changes ### API Checklist - [ ] `GET /v1/health` - [ ] `GET /v1/state` auth behavior - [ ] `POST /v1/command` - [ ] `POST /v1/commands` ### Result - Current Status: `Fix Implemented` - Notes: build/check/qa validation passed; manual runtime visual verification still required. ## Status History - `2026-02-13 13:20` - reporter - `Reported` - runtime screenshot captured with `TypeError: W.fromURL is not a function`. - `2026-02-13 13:35` - codex - `Triaged` - localized failure to Pixi atlas loader path. - `2026-02-13 13:55` - codex - `In Progress` - replaced loader API and hardened renderer lifecycle. - `2026-02-13 14:05` - codex - `Fix Implemented` - patch completed, verification checklist queued. - `2026-02-13 14:20` - codex - `Fix Implemented` - checks passed (`cargo check`, UI build, QA validation); smoke launch attempted. - `2026-02-13 14:35` - codex - `Fix Implemented` - added build-script change tracking for frontend assets to prevent stale embedded UI. - `2026-02-13 14:55` - codex - `In Progress` - removed all runtime `fromURL` usage from renderer atlas loading path. - `2026-02-13 15:05` - codex - `In Progress` - added explicit UI build marker to detect stale executable/frontend embedding. - `2026-02-13 15:20` - reporter - `In Progress` - provided `issue2-after-fix3` screenshot; stale-build issue resolved, permission + chroma-key defects observed. - `2026-02-13 15:35` - codex - `Fix Implemented` - added tauri capability permission file and tauri-side chroma-key conversion. ## Closure - Current Status: `Fix Implemented` - Close Date: - Owner: - Linked PR/commit: