73 lines
2.8 KiB
Markdown
73 lines
2.8 KiB
Markdown
---
|
|
id: LSN-0054
|
|
ticket: hub-suspended-game-kill-affordance
|
|
title: Manual Hub Kill Must Share Game Termination Cleanup
|
|
created: 2026-07-05
|
|
tags: [hub, lifecycle, game, ui, assets]
|
|
---
|
|
|
|
## Context
|
|
|
|
After a Game returns to Home, the Game can remain resident and suspended so it
|
|
can be resumed later. That state needs a visible, direct way to terminate the
|
|
resident Game without launching another cartridge just to force replacement.
|
|
|
|
The Hub kill affordance solved the UX gap, but the durable engineering lesson is
|
|
the cleanup boundary: manual kill must not become a second, partial termination
|
|
path.
|
|
|
|
## Key Decisions
|
|
|
|
### Hub Suspended Game Kill Affordance
|
|
|
|
**What:** Hub renders a red bottom-right control when a Game is resident and
|
|
suspended. The control shows only the Game title. Clicking it immediately
|
|
terminates the resident Game and keeps the user in Hub.
|
|
|
|
**Why:** The user can distinguish "resume this Game" from "discard this resident
|
|
Game" without starting a different cartridge. Reusing the canonical termination
|
|
path prevents a repeat of stale scene/glyph/asset state bugs.
|
|
|
|
**Trade-offs:** V1 has no confirmation step. The destructive nature is carried
|
|
by placement, color, and the fact that the target Game is already out of
|
|
foreground.
|
|
|
|
## Patterns and Algorithms
|
|
|
|
Manual Hub kill and destructive Game replacement should call the same resident
|
|
Game termination helper. That helper is responsible for the whole runtime
|
|
surface:
|
|
|
|
- close the Game task;
|
|
- stop the process;
|
|
- remove the VM session;
|
|
- clear resident Game state and task-scoped lifecycle delivery;
|
|
- restore Shell/Hub render ownership;
|
|
- clear lifecycle audio pause state;
|
|
- unbind the Game2D composer scene;
|
|
- shut down cartridge-scoped asset manager state and physical banks;
|
|
- emit explicit Hub/POS observability for manual kill.
|
|
|
|
The Hub itself should emit a high-level action such as `KillResidentGame`; it
|
|
should not know how to clean runtime subsystems.
|
|
|
|
## Pitfalls
|
|
|
|
- A UI-only kill that removes a task but leaves assets or composer binding alive
|
|
can still fail later when another Game renders.
|
|
- A cleanup-only helper without an end-to-end Hub click test can miss the
|
|
interaction between hitbox, foreground ownership, render owner, and no-resume.
|
|
- Hard-coded click coordinates in tests make the UI contract harder to maintain;
|
|
expose the layout hitbox when tests need to exercise it.
|
|
|
|
## Takeaways
|
|
|
|
- Visible system controls should produce system actions, not direct subsystem
|
|
mutation from UI code.
|
|
- Manual kill and Game replacement are variants of the same resident Game
|
|
termination contract.
|
|
- Cleanup tests should prove both logical state removal and visible-frame
|
|
behavior: the control appears before kill and disappears after kill.
|
|
- "No resume after kill" is as important as "task closed" because resumability
|
|
is the user-facing state.
|