Skip to content

refactor(stage): enforce package boundaries - #2371

Closed
leaft wants to merge 1 commit into
moeru-ai:mainfrom
leaft:feat/package-boundaries
Closed

refactor(stage): enforce package boundaries#2371
leaft wants to merge 1 commit into
moeru-ai:mainfrom
leaft:feat/package-boundaries

Conversation

@leaft

@leaft leaft commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR removes five cross-package source imports and gives shared Stage behavior a clear owner.

It resolves all five findings from the package-boundary review. Items 3 and 4 share one boundary and use one solution.

Problems and solutions

Item Problem Solution
1 Stage Web and Stage Pocket kept identical Polaroid pages. Each app had to maintain the same route-level behavior. Move the unchanged page to @proj-airi/stage-pages. Both apps already scan this shared page directory. Update the browser regression test to import the public package path.
2 @proj-airi/stage-ui imported useSettingsLive2d from the stage-ui-live2d source tree. This bypassed the package export contract. Import useSettingsLive2d from @proj-airi/stage-ui-live2d.
3 and 4 The VRM and MMD renderers each imported the Stage audio store from the stage-ui source tree. They also copied the same wLipSync profile and model-neutral vowel policy. Pass the owning AudioContext from Stage to both renderers. Move the shared profile and vowel policy to @proj-airi/model-driver-lipsync. Keep the VRM and MMD model mappings in their renderer packages.
5 The MCP store imported useLocalStorageManualReset from the stage-shared source tree. Import the composable from the public @proj-airi/stage-shared/composables entry.

Lip-sync boundary

Stage owns AudioContext and the current audio source
  -> ThreeScene / MMDScene receive both as inputs
    -> model-driver-lipsync owns the profile and shared vowel policy
      -> VRM maps AEIOU to aa / ee / ih / oh / ou
      -> MMD maps AEIOU to vowelA / vowelE / vowelI / vowelO / vowelU

The shared driver does not depend on Vue, Three.js, VRM, or MMD. The renderer packages no longer depend directly on wlipsync.

The renderer packages also no longer import the Stage audio store. Audio cleanup disconnects only the wLipSync node that each renderer owns.

Visual changes

No visual changes. The shared Polaroid SFC is byte-for-byte identical to both removed app copies. The browser regression test passes from the new package location.

Verification

  • sem diff --staged --no-cosmetics -v --file-exts .ts .tsx
  • sem diff --staged --no-cosmetics -v --file-exts .vue
  • pnpm -F @proj-airi/model-driver-lipsync test — 3 tests passed
  • pnpm -F @proj-airi/stage-ui-three exec vitest run — 18 tests passed
  • pnpm -F @proj-airi/stage-ui-mmd exec vitest run — 23 tests passed
  • pnpm -F @proj-airi/stage-web exec vitest run --config vitest.config.ts src/pages/devtools/polaroid.browser.test.ts — 1 browser test passed
  • Type checks passed for model-driver-lipsync, stage-ui-three, stage-ui-mmd, stage-ui, stage-pages, stage-web, and stage-pocket
  • pnpm lint — 0 errors and 7 existing warnings outside this change
  • git diff --check

The full pnpm typecheck still reports three errors in the unchanged apps/stage-tamagotchi/src/renderer/main.ts.

vue-router/auto-routes does not export handleHotUpdate or routes. The updatedRoutes parameter also has an implicit any type.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

⏳ Approval required for deploying to Cloudflare Workers (Preview) for stage-web.

Name Link
🔭 Waiting for approval For maintainers, approve here

Hey, maintainers, kindly take some time to review and approve this deployment when you are available. Thank you! 🙏

@leaft
leaft force-pushed the feat/package-boundaries branch from 917392f to c822c74 Compare August 26, 2026 09:42
@leaft

leaft commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

Replaced by three independent Draft PRs, each with its own branch and commit: #2375 for the shared Polaroid page, #2373 for public package exports, and #2374 for the shared lip-sync boundary.

@leaft leaft closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants