SystemOS Cartridge Switch Orchestrator

This commit is contained in:
bQUARKz 2026-07-05 01:03:02 +01:00
parent 313b896e7b
commit 0ffb3467b1
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
9 changed files with 775 additions and 22 deletions

View File

@ -1,5 +1,5 @@
{"type":"meta","next_id":{"DSC":44,"AGD":47,"DEC":39,"PLN":157,"LSN":53,"CLSN":1}} {"type":"meta","next_id":{"DSC":44,"AGD":47,"DEC":40,"PLN":163,"LSN":53,"CLSN":1}}
{"type":"discussion","id":"DSC-0043","status":"open","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-03","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[{"id":"AGD-0044","file":"AGD-0044-systemos-cartridge-switch-orchestrator.md","status":"open","created_at":"2026-07-03","updated_at":"2026-07-03"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0043","status":"in_progress","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[{"id":"AGD-0044","file":"AGD-0044-systemos-cartridge-switch-orchestrator.md","status":"accepted","created_at":"2026-07-03","updated_at":"2026-07-05"}],"decisions":[{"id":"DEC-0039","file":"DEC-0039-systemos-game-cartridge-switch-orchestrator.md","status":"accepted","created_at":"2026-07-05","updated_at":"2026-07-05","ref_agenda":"AGD-0044"}],"plans":[{"id":"PLN-0157","file":"PLN-0157-introduce-systemos-game-switch-target-contract.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]},{"id":"PLN-0158","file":"PLN-0158-terminate-resident-game-before-switching-cartridges.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]},{"id":"PLN-0159","file":"PLN-0159-recover-failed-game-switches-back-to-home.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]},{"id":"PLN-0160","file":"PLN-0160-add-dummy-boy-visual-switch-test-cartridge.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]},{"id":"PLN-0161","file":"PLN-0161-validate-stress-to-dummy-boy-game-switch-end-to-end.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]},{"id":"PLN-0162","file":"PLN-0162-specify-game-switch-contract-and-direct-boot-separation.md","status":"open","created_at":"2026-07-05","updated_at":"2026-07-05","ref_decisions":["DEC-0039"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."} {"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
{"type":"discussion","id":"DSC-0040","status":"done","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-06","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0040-vm-render-parallel-execution-boundary/LSN-0048-render-workers-need-a-closed-packet-contract.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-06"}]} {"type":"discussion","id":"DSC-0040","status":"done","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-06","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0040-vm-render-parallel-execution-boundary/LSN-0048-render-workers-need-a-closed-packet-contract.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-06"}]}
{"type":"discussion","id":"DSC-0041","status":"done","ticket":"foreground-stack-game-pause-shell-vm-backed","title":"Foreground Stack, Game Pause, and VM-Backed Shell Coexistence","created_at":"2026-06-05","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","shell","game","vm","foreground","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0041-foreground-stack-game-pause-shell-vm-backed/LSN-0052-foreground-ownership-and-vm-session-ownership-are-separate.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]} {"type":"discussion","id":"DSC-0041","status":"done","ticket":"foreground-stack-game-pause-shell-vm-backed","title":"Foreground Stack, Game Pause, and VM-Backed Shell Coexistence","created_at":"2026-06-05","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","shell","game","vm","foreground","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0041-foreground-stack-game-pause-shell-vm-backed/LSN-0052-foreground-ownership-and-vm-session-ownership-are-separate.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]}

View File

@ -2,7 +2,7 @@
id: AGD-0044 id: AGD-0044
ticket: system-os-cartridge-switch-orchestrator ticket: system-os-cartridge-switch-orchestrator
title: SystemOS Cartridge Switch Orchestrator title: SystemOS Cartridge Switch Orchestrator
status: open status: accepted
created: 2026-07-03 created: 2026-07-03
resolved: resolved:
decision: decision:
@ -90,35 +90,58 @@ pode cair em estados incoerentes:
## Sugestao / Recomendacao ## Sugestao / Recomendacao
Recomendo a Opcao A agora, com esta agenda aberta como marcador explicito de `DSC-0041` foi fechada e o contrato de foreground/pausa/resume ja existe. A
escopo futuro. recomendacao agora deixa de ser adiar e passa a ser fechar uma decisao curta
para o orquestrador de troca `Game A -> Home -> Game B`.
A ordem preferida passa a ser: O contrato sugerido e:
1. fechar a `AGD-0041` para definir foreground, pausa/suspensao, Shell no - trocar para outro Game e uma substituicao controlada, nao uma pausa/resume;
foreground e retorno ao mesmo Game; - o Game residente anterior e fechado/descartado;
2. voltar para esta agenda e decidir o contrato do orquestrador de troca de - a VM session do Game anterior e removida;
cartucho no SystemOS; - o novo Game sempre recebe uma VM session nova e zerada;
3. so entao planejar a execucao de `Game A -> Home -> Game B`. - se o novo load falhar, o sistema volta ao Home/Hub com diagnostico e nao
tenta preservar o Game anterior em v1;
Se durante a `AGD-0041` aparecer uma decisao que exige antecipar parte do - o loader continua sendo etapa interna, sem possuir politica de lifecycle;
orquestrador, esta agenda deve ser reaberta/atualizada com a dependencia - a evidencia minima deve usar dois cartuchos distintos, incluindo um cartucho
concreta em vez de esconder a troca de cartucho dentro da agenda de foreground. simplista `dummy-boy` alem do stress test.
## Perguntas em Aberto ## Perguntas em Aberto
- [ ] Depois da `AGD-0041`, qual estado representa um Game que sera descartado - [x] Depois da `AGD-0041`, qual estado representa um Game que sera descartado
em vez de retomado? em vez de retomado?
- [ ] O fechamento do Game atual e observavel para o firmware/game, ou e uma - Resposta: fechamento/encerramento controlado, nao `PausedSuspended`. O Game
anterior deixa de ser resident/resumable e sua VM session e removida.
- [x] O fechamento do Game atual e observavel para o firmware/game, ou e uma
destruicao interna do SystemOS? destruicao interna do SystemOS?
- [ ] Quais estados cartridge-scoped devem ser limpos antes do novo load: VM, - Resposta: deve ser observavel como uma transicao de lifecycle/firmware, mas
nao cooperativo nem bloqueante para o Game. O SystemOS tem autoridade para
encerrar e descartar a sessao. Pode ser emitido um evento de encerramento
para permitir save/flush cooperativo quando existir esse mecanismo, mas a
troca nao deve depender da resposta do Game.
- [x] Quais estados cartridge-scoped devem ser limpos antes do novo load: VM,
assets, FS handles, input, audio, render ownership, telemetry, logs? assets, FS handles, input, audio, render ownership, telemetry, logs?
- [ ] Se o novo cartucho falha ao carregar, o sistema volta ao Home, mostra uma - Resposta: a troca nao reaproveita VM. O Game anterior e encerrado, sua VM
session e descartada, e o novo Game recebe VM/session nova e zerada. Devem
ser limpos ou reatribuídos os estados cartridge-scoped ligados a VM,
handles abertos, input pendente/barreiras, audio do app, render ownership,
telemetry/debug/crash state do app. Logs historicos podem permanecer como
observabilidade.
- [x] Se o novo cartucho falha ao carregar, o sistema volta ao Home, mostra uma
tela de erro, ou tenta preservar o Game anterior? tela de erro, ou tenta preservar o Game anterior?
- [ ] Como a resolucao do novo alvo e representada sem depender de catalogo - Resposta: o Game anterior ja foi encerrado. Se o novo load falha, a sessao
parcial do novo Game e descartada e o sistema volta ao Home/Hub com
diagnostico. Preservar o Game anterior fica fora de escopo em v1.
- [x] Como a resolucao do novo alvo e representada sem depender de catalogo
completo ou `.pmc`? completo ou `.pmc`?
- [ ] Qual evidencia minima prova `Game A -> Home -> Game B` sem depender de UX - Resposta: para o contrato minimo, o alvo pode ser um path/entrada ja
resolvido pelo Hub/game library atual. O contrato nao depende de `.pmc` nem
de catalogo final.
- [x] Qual evidencia minima prova `Game A -> Home -> Game B` sem depender de UX
final de launcher? final de launcher?
- Resposta: criar um cartucho `dummy-boy` ao lado do stress test. O teste deve
provar `Stress -> Home -> Dummy Boy`, com troca de VM session, identidade de
cartridge distinta e render observavel do novo Game.
## Criterio para Encerrar ## Criterio para Encerrar
@ -139,7 +162,17 @@ A agenda pode virar decisao quando:
O novo escopo cobre a troca posterior `Game A -> Home -> Game B`, com O novo escopo cobre a troca posterior `Game A -> Home -> Game B`, com
orquestracao pelo SystemOS depois que o contrato de foreground estiver orquestracao pelo SystemOS depois que o contrato de foreground estiver
fechado. fechado.
- 2026-07-05: Apos fechamento de `DSC-0041`, a discussao convergiu para troca
destrutiva simples em v1: ao iniciar outro Game, o Game residente anterior e
encerrado, sua VM session e removida, e o novo Game recebe VM session nova.
Falha de load volta ao Home/Hub com diagnostico. A evidencia minima deve
incluir um novo cartucho `dummy-boy` que desenha um quadrado com cores
oscilando, alem do stress test.
- 2026-07-05: Refinamento: o encerramento do Game anterior pode emitir evento
cooperativo para save/flush, mas esse evento nao e uma permissao nem uma
barreira obrigatoria. O SystemOS continua com autoridade para concluir a troca
e remover a VM session anterior.
## Resolution ## Resolution
Ainda em aberto. Pronta para virar decisao, pendente confirmacao explicita do usuario.

View File

@ -0,0 +1,174 @@
---
id: DEC-0039
ticket: system-os-cartridge-switch-orchestrator
title: SystemOS Game Cartridge Switch Orchestrator
status: accepted
created: 2026-07-05
ref_agenda: AGD-0044
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Status
Open for review.
## Contexto
`DEC-0037` fechou o contrato `Game -> Home/Shell -> mesmo Game`: o Game pode
ficar residente, ser pausado/suspenso pelo SystemOS, e depois ser retomado.
`DEC-0038` fechou o ownership de VM sessions: VM-backed mutable execution state
pertence a sessoes de VM associadas a processos/tarefas, nao a uma VM global do
firmware.
Esta decision cobre outro fluxo: `Game A -> Home -> Game B`. Nesse caso, o
usuario nao esta retomando o mesmo Game. O usuario esta escolhendo substituir o
Game residente por outro cartucho. Essa substituicao precisa ser orquestrada
pelo SystemOS, nao pelo loader e nao por userland.
## Decisao
PROMETEU MUST tratar `Game A -> Home -> Game B` como uma substituicao
controlada de Game, nao como pause/resume.
Quando o usuario escolher iniciar um Game diferente enquanto ja existe um Game
residente, SystemOS MUST encerrar o Game residente anterior, remover sua
resident state e descartar sua VM session antes de ativar o novo Game como
resident/foreground.
O Game anterior MAY receber um evento cooperativo de encerramento para permitir
save/flush quando esse mecanismo existir. Esse evento MUST NOT ser uma
permissao, veto ou barreira obrigatoria para a troca. SystemOS MUST manter
autoridade para concluir a troca e remover a VM session anterior mesmo se o
Game nao reagir.
O novo Game MUST receber uma VM session nova e zerada. A troca MUST NOT
reutilizar a VM session, PC, stack, heap, globals, open handles, cartridge
identity, lifecycle state, debug state ou runtime state do Game anterior.
O loader/materializador de cartridge MUST permanecer uma etapa interna de
carregamento. Ele MUST NOT possuir politica de lifecycle, foreground,
close/discard, cleanup ou recuperacao de falha.
Se o novo cartucho falhar ao carregar, SystemOS MUST descartar qualquer session
parcial ou estado cartridge-scoped parcial do novo Game e retornar ao Home/Hub
com diagnostico. V1 MUST NOT tentar preservar ou restaurar o Game anterior
depois que a troca tiver comecado.
Boot direto por CLI/debug permanece um caminho separado e mais simples. Esta
decision governa troca de Game sob SystemOS depois que o usuario retorna ao
Home/Hub.
A evidencia minima de implementacao MUST incluir dois test cartridges
distintos: o stress cartridge existente e um novo cartridge `dummy-boy`.
`dummy-boy` MUST renderizar um quadrado visualmente distinto com cor oscilante
para que os testes provem que o segundo Game, e nao um frame/session anterior
stale, esta ativo.
## Rationale
Trying to preserve Game A while loading Game B would turn the switch into a
transactional snapshot/rollback problem. That is not needed for v1 and would
pull in VM snapshot correctness, open handle restoration, assets, render
ownership rollback, audio rollback, input state, debugger state, and telemetry
rollback.
The simpler and safer v1 contract is destructive replacement:
1. the user requests another Game;
2. SystemOS ends the previous resident Game;
3. SystemOS removes its VM session and cartridge-scoped runtime state;
4. SystemOS attempts to load the new Game into a fresh VM session;
5. success enters the new Game;
6. failure returns to Home/Hub with diagnostic.
This aligns with `DEC-0037` because pause/suspend remains the same-Game resume
flow. It aligns with `DEC-0038` because VM identity is session-owned and each
Game receives a distinct VM session.
## Invariantes / Contrato
- SystemOS is the authority for switching from one Game cartridge to another
under Home/Hub.
- `Game -> Home -> same Game` is pause/resume and remains governed by
`DEC-0037`.
- `Game A -> Home -> Game B` is destructive replacement and is governed by this
decision.
- A Game that is being replaced MUST stop being resident/resumable.
- The previous Game VM session MUST be removed before the new Game becomes the
active resident/foreground Game.
- A cooperative close/terminate/save event MAY be delivered to the previous
Game, but it MUST NOT block replacement.
- The new Game MUST get a fresh VM session.
- The new Game MUST NOT inherit VM execution state, open handles, lifecycle
delivery state, cartridge identity, debug state, telemetry state, or crash
state from the previous Game.
- Render ownership MUST transition through SystemOS ownership policy and stale
submissions from the previous Game MUST NOT be presented after the switch.
- Input pending/barrier state MUST be cleared or made safe across the switch.
- App audio from the previous Game MUST be stopped or detached from the active
app before the new Game becomes foreground.
- Logs MAY remain as historical observability; they are not cartridge execution
state.
- If new Game load fails, Home/Hub is the recovery state for v1.
- V1 does not preserve, restore, or rollback to the previous Game after a
switch begins.
- The launcher target MAY be a path or already-resolved game-library entry for
v1. `.pmc` and final catalog UX are out of scope.
- `run_cart`, if retained, is not a userland command and not the switch
orchestrator.
## Impactos
- **Runtime / SystemOS:** needs an explicit Game switch orchestration path that
closes/removes the current resident Game session before loading the next Game.
- **Lifecycle:** needs a controlled replacement transition distinct from
pause/suspend/resume.
- **VM sessions:** previous Game session removal and new Game session creation
are mandatory switch steps.
- **Firmware:** should observe macro states such as Home, loading, load failure,
and GameRunning, but should not own switch policy.
- **Hub / launcher:** should request a switch through SystemOS using a resolved
target; it should not call a loader directly as lifecycle authority.
- **Loader:** remains a materialization step and returns success/failure without
owning cleanup policy.
- **Renderer:** render ownership/stale submission invalidation must prove the
new Game owns current presentation after success.
- **Input/audio:** previous Game input/audio must not leak into the new Game.
- **Tests:** need a second visually distinct test cartridge, `dummy-boy`, to
prove Game identity and render transition.
## Alternativas Descartadas
- **Preserve Game A until Game B loads successfully:** rejected for v1 because it
requires rollback semantics across VM, assets, handles, render ownership,
input, audio, debugger, and telemetry.
- **Treat Game A -> Game B as pause/resume:** rejected because a different Game
should not inherit resumable state from the previous Game.
- **Let the loader close the previous Game:** rejected because loader/materializer
should not own lifecycle policy.
- **Reuse the previous VM session for the new Game:** rejected because it
violates VM session ownership and risks state leakage.
- **Depend on `.pmc` or final catalog UX now:** rejected because the lifecycle
contract can be validated using path/game-library targets first.
## Referencias
- Source agenda: `AGD-0044`
- Foreground stack and Game pause contract: `DEC-0037`
- VM session ownership for VM-backed processes: `DEC-0038`
- SystemOS lifecycle/process/task authority: `DSC-0032`
- Launch authority lesson: `LSN-0051`
- Foreground/session ownership lesson: `LSN-0052`
## Propagacao Necessaria
- Add/update runtime spec for Game cartridge switching under SystemOS.
- Add implementation plans for:
- SystemOS switch orchestration;
- resident Game termination/session removal;
- fresh session load for the new Game;
- failure recovery to Home/Hub;
- `dummy-boy` test cartridge;
- end-to-end `Stress -> Home -> Dummy Boy` validation.
- Ensure host/debug direct boot remains separate from SystemOS Game switch.

View File

@ -0,0 +1,86 @@
---
id: PLN-0157
ticket: system-os-cartridge-switch-orchestrator
title: Introduce SystemOS Game Switch Target Contract
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 requires Game-to-Game switching under Home/Hub to be owned by SystemOS.
Before destructive replacement can be implemented, Hub/Firmware/SystemOS need a
small explicit contract for "launch this resolved Game target as a replacement"
that is separate from direct boot and from loader internals.
## Objective
Introduce a SystemOS-owned Game switch request/target abstraction that can carry
a resolved cartridge path or game-library entry from Hub/Home into the switch
orchestrator without making the loader or userland the lifecycle authority.
## Dependencies
- Source decision: DEC-0039.
- Builds on DEC-0037 and DEC-0038 as already implemented.
- Must be implemented before PLN-0158, PLN-0159, and PLN-0161.
## Scope
- Define a minimal Game switch target type, such as `GameSwitchTarget` or
`CartridgeLaunchTarget`, in the SystemOS/Firmware boundary.
- Route Hub game-library launch actions through that target contract instead of
treating a path as an implicit lifecycle operation.
- Keep direct boot/debug boot paths separate from SystemOS Game switching.
- Add tests proving the target preserves cartridge identity/path without
starting lifecycle replacement by itself.
## Non-Goals
- Do not implement destructive replacement in this plan.
- Do not add `.pmc`, final catalog UX, or a new launcher UI.
- Do not change direct CLI/debug boot behavior.
- Do not add background execution.
## Execution Method
1. Inspect `crates/console/prometeu-system/src/services/game_library.rs`,
`crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs`,
and `crates/console/prometeu-firmware/src/firmware/firmware_step_hub_home.rs`.
2. Add a minimal launch target model at the SystemOS/Firmware boundary:
- resolved cartridge path;
- optional app_id/title metadata if already available;
- no loader-owned lifecycle policy.
3. Update Hub action plumbing so `SystemProfileAction::LaunchGame` carries the
resolved target type or maps immediately into it at the firmware boundary.
4. Add a placeholder SystemOS/Firmware entry point for Game switching that
accepts the target but still delegates to the existing load path until
PLN-0158 changes replacement behavior.
5. Add unit tests for target construction and path propagation.
6. Keep direct `BootTarget::Cartridge` behavior unchanged.
## Acceptance Criteria
- There is an explicit type or function contract representing a resolved
SystemOS Game switch target.
- Hub/Home no longer treats a raw path as lifecycle authority.
- The loader remains a materialization step, not the switch orchestrator.
- Direct boot/debug boot code paths remain separate and behaviorally unchanged.
- Tests prove target identity is carried without implicitly closing or loading a
Game.
## Tests
- `cargo test -p prometeu-system`
- `cargo test -p prometeu-firmware`
- `cargo test -p prometeu-host-desktop-winit`
- `cargo clippy -p prometeu-system -p prometeu-firmware -p prometeu-host-desktop-winit --all-targets -- -D warnings`
## Affected Artifacts
- `crates/console/prometeu-system/src/services/game_library.rs`
- `crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_hub_home.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware.rs`

View File

@ -0,0 +1,98 @@
---
id: PLN-0158
ticket: system-os-cartridge-switch-orchestrator
title: Terminate Resident Game Before Switching Cartridges
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 defines `Game A -> Home -> Game B` as destructive replacement. The
current same-Game resume flow keeps the resident Game session alive; switching
to a different Game must instead close/remove that resident session and create a
fresh session for the new Game.
## Objective
Implement the SystemOS lifecycle/session operation that terminates the current
resident Game before loading a different Game cartridge.
## Dependencies
- Source decision: DEC-0039.
- Requires PLN-0157 target contract.
- Should be implemented before PLN-0159 and PLN-0161.
## Scope
- Add a controlled resident Game termination/replacement operation to SystemOS
lifecycle/session services.
- Optionally emit a cooperative terminate/close/save lifecycle event when the
current event model can carry it, but do not block replacement on it.
- Remove the previous Game from resident/resumable state.
- Remove the previous Game VM session before activating the new Game.
- Clear or reassign app-scoped state that cannot leak into the new Game:
session VM, open handles, pending lifecycle state, input barrier/pending
input, audio active app state, render ownership, telemetry/debug/crash state.
## Non-Goals
- Do not preserve Game A for rollback.
- Do not implement failed-load recovery beyond surfacing errors; that is
PLN-0159.
- Do not add background execution or multiple resident Games.
- Do not build final launcher UX.
## Execution Method
1. Inspect lifecycle/session state in:
- `crates/console/prometeu-system/src/os/lifecycle.rs`;
- `crates/console/prometeu-system/src/os/facades/sessions.rs`;
- `crates/console/prometeu-system/src/services/foreground`;
- `crates/console/prometeu-firmware/src/firmware/firmware_step_hub_home.rs`;
- `crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs`.
2. Add a `replace_resident_game` or equivalent operation that:
- finds the current resident Game;
- marks its task/process closed or stopped according to existing lifecycle
semantics;
- removes the resident Game entry from foreground stack/lifecycle state;
- removes its VM session.
3. Ensure same-Game resume still bypasses replacement and remains governed by
DEC-0037.
4. Update game launch from Home so launching a different app_id triggers
replacement before load.
5. Ensure render ownership transitions away from the old Game before the new
Game becomes foreground.
6. Add focused tests for resident Game termination and session removal.
## Acceptance Criteria
- Launching a different Game from Home closes/removes the resident Game rather
than resuming it.
- The previous Game VM session is absent before the new Game is made active.
- Same-Game selection still resumes the existing resident Game.
- A cooperative close/terminate event, if added, is non-blocking.
- No previous Game VM, handle, lifecycle, render, or debug state is reused by
the new Game.
## Tests
- `cargo test -p prometeu-system`
- `cargo test -p prometeu-firmware`
- `cargo clippy -p prometeu-system -p prometeu-firmware --all-targets -- -D warnings`
- Add tests for:
- different Game launch removes previous resident session;
- same Game launch resumes existing resident session;
- old Game task/process state is closed/stopped;
- old Game session cannot be resolved after replacement starts.
## Affected Artifacts
- `crates/console/prometeu-system/src/os/lifecycle.rs`
- `crates/console/prometeu-system/src/os/facades/sessions.rs`
- `crates/console/prometeu-system/src/services/foreground`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_hub_home.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs`

View File

@ -0,0 +1,86 @@
---
id: PLN-0159
ticket: system-os-cartridge-switch-orchestrator
title: Recover Failed Game Switches Back To Home
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 rejects preserving Game A after a switch begins. If Game B fails to
load, the system must discard partial Game B state and return to Home/Hub with a
diagnostic, not attempt rollback to Game A.
## Objective
Implement controlled failed-switch recovery to Home/Hub after destructive Game
replacement begins.
## Dependencies
- Source decision: DEC-0039.
- Requires PLN-0157 target contract.
- Requires PLN-0158 resident Game termination/session removal.
## Scope
- Detect load/init failure while switching to a different Game.
- Discard any partial new Game task/session/window/render/input/audio state.
- Return firmware/SystemOS to Home/Hub.
- Log or expose a diagnostic that Home can surface or tests can assert.
- Ensure previous Game is not restored after switch failure.
## Non-Goals
- Do not implement transactional rollback.
- Do not preserve the previous Game after switch begins.
- Do not design final user-facing error UI.
- Do not change direct boot failure behavior unless needed to keep paths
separate.
## Execution Method
1. Inspect existing load failure flow in
`crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs`.
2. Add a switch-specific failure outcome or context flag that distinguishes
SystemOS Game switching from direct boot load.
3. On switch load failure:
- remove partial new VM session/task/process if created;
- clear partial cartridge-scoped state;
- transition to `HubHome` instead of app crash when appropriate for switch
recovery;
- log a diagnostic containing target identity/path and failure summary.
4. Preserve existing direct boot and explicit load failure tests unless a direct
boot path intentionally still goes to crash.
5. Add tests for bad Game B after Game A was already terminated.
## Acceptance Criteria
- Failed `Game A -> Home -> Broken Game B` returns to Home/Hub.
- Previous Game A is not resident, resumable, or restored.
- Partial Game B VM session/task/process state is removed or closed.
- A diagnostic is logged or otherwise observable.
- Existing direct boot/debug boot failure semantics remain separate.
## Tests
- `cargo test -p prometeu-firmware`
- `cargo test -p prometeu-system`
- `cargo test -p prometeu-host-desktop-winit`
- `cargo clippy -p prometeu-system -p prometeu-firmware -p prometeu-host-desktop-winit --all-targets -- -D warnings`
- Add tests for:
- switch failure returns Home;
- old Game not restored;
- partial new session cleanup;
- direct boot failure path remains unchanged.
## Affected Artifacts
- `crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_hub_home.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware.rs`
- `crates/console/prometeu-system/src/os/facades/sessions.rs`
- `crates/console/prometeu-system/src/os/lifecycle.rs`

View File

@ -0,0 +1,90 @@
---
id: PLN-0160
ticket: system-os-cartridge-switch-orchestrator
title: Add Dummy Boy Visual Switch Test Cartridge
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 requires minimum evidence using two distinct test cartridges. The
existing stress cartridge proves execution/logging but is not visually distinct
enough for switch validation. A second cartridge, `dummy-boy`, must render an
oscillating-color square.
## Objective
Add a simple `test-cartridges/dummy-boy` cartridge that renders a visible square
with changing colors so Game switching can prove visual/session identity.
## Dependencies
- Source decision: DEC-0039.
- Can be implemented independently of PLN-0157 through PLN-0159.
- Required before PLN-0161 end-to-end validation.
## Scope
- Add `test-cartridges/dummy-boy/manifest.json`.
- Generate or add `test-cartridges/dummy-boy/program.pbx`.
- Add empty or minimal assets payload if the loader requires `assets.pa`.
- Implement Dummy Boy behavior:
- Game cartridge identity distinct from stress;
- deterministic visible square;
- color oscillates across frames;
- no dependency on final launcher UX.
- Add build/generation documentation or tests so the cartridge can be
regenerated safely if needed.
## Non-Goals
- Do not add final game content.
- Do not add `.pmc`.
- Do not depend on host screenshots for the first validation unless an existing
harness already supports it.
- Do not change stress cartridge behavior.
## Execution Method
1. Inspect the stress cartridge and any PBX generator tooling:
- `test-cartridges/stress-console`;
- `crates/tools/pbxgen-stress`;
- bytecode assembler helpers in `crates/console/prometeu-bytecode`.
2. Choose the smallest maintainable generator path:
- extend existing PBX generator if appropriate; or
- add a focused `pbxgen-dummy-boy` tool; or
- add deterministic generated PBX with source instructions.
3. Create `manifest.json` with unique `app_id`, title `Dummy Boy`, Game mode,
and version.
4. Generate `program.pbx` that renders the square and advances color over
frames.
5. Add tests or smoke checks that the cartridge is discoverable by games-root
discovery.
## Acceptance Criteria
- `test-cartridges/dummy-boy` exists and loads as a Game cartridge.
- Dummy Boy has a unique `app_id` and title distinct from Stress.
- Dummy Boy renders a visible square.
- Square color changes deterministically over time.
- Games-root discovery sees both Stress and Dummy Boy.
- Existing stress cartridge remains unchanged.
## Tests
- `cargo test -p prometeu-hal`
- `cargo test -p prometeu-system`
- `cargo test -p prometeu-firmware`
- Run any cartridge generator tests added by this plan.
- Add or update tests for games-root discovery including Dummy Boy.
## Affected Artifacts
- `test-cartridges/dummy-boy/manifest.json`
- `test-cartridges/dummy-boy/program.pbx`
- `test-cartridges/dummy-boy/assets.pa` if required
- `crates/tools/*` cartridge generator tooling if needed
- `crates/console/prometeu-system/src/services/game_library.rs` tests if needed

View File

@ -0,0 +1,93 @@
---
id: PLN-0161
ticket: system-os-cartridge-switch-orchestrator
title: Validate Stress To Dummy Boy Game Switch End To End
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 requires proof that `Game A -> Home -> Game B` creates a fresh Game
session and does not present stale state from Game A. The minimum evidence is
switching from Stress to Dummy Boy.
## Objective
Add end-to-end validation for `Stress -> Home -> Dummy Boy` through the real
Hub/Home flow, proving lifecycle, VM session, cartridge identity, and render
ownership switch correctly.
## Dependencies
- Source decision: DEC-0039.
- Requires PLN-0157 target contract.
- Requires PLN-0158 destructive replacement.
- Requires PLN-0159 failed-switch recovery for negative path assertions.
- Requires PLN-0160 Dummy Boy cartridge.
## Scope
- Add firmware/system tests that drive:
- launch Stress from games root;
- request Home;
- launch Dummy Boy;
- assert Stress session is gone;
- assert Dummy Boy session is active;
- assert cartridge identity and render ownership belong to Dummy Boy.
- Add a negative end-to-end test for broken Game B returning to Home if not
already covered by PLN-0159.
- Use existing test platform/render submission inspection where possible.
## Non-Goals
- Do not require final launcher UX.
- Do not add screenshot-based host automation unless existing test utilities
make it cheap and deterministic.
- Do not implement additional Game-to-Game variants beyond Stress to Dummy Boy.
## Execution Method
1. Inspect existing firmware tests in
`crates/console/prometeu-firmware/src/firmware/firmware.rs`.
2. Reuse existing `TestGameRoot` or games-root helpers to expose Stress and
Dummy Boy.
3. Drive input through Hub/Home selection rather than calling cartridge load
directly when possible.
4. Assert lifecycle/session invariants:
- old task closed/stopped;
- old VM session removed;
- new VM session created;
- foreground owner is new Game;
- current cartridge identity is Dummy Boy.
5. Assert render invariants:
- render ownership epoch belongs to Dummy Boy app identity;
- stale Stress submissions are not accepted after switch;
- latest observable Game frame comes from Dummy Boy when render inspection is
available.
6. Add a focused test for failure path if missing after PLN-0159.
## Acceptance Criteria
- End-to-end test proves Stress can be replaced by Dummy Boy from Home.
- Stress is not resumable after switching to Dummy Boy.
- Dummy Boy receives a fresh VM session.
- Cartridge identity and active render ownership are Dummy Boy after switch.
- Failure path returns Home and does not restore Stress.
- Tests are deterministic and do not rely on manual host interaction.
## Tests
- `cargo test -p prometeu-firmware`
- `cargo test -p prometeu-system`
- `cargo test -p prometeu-host-desktop-winit`
- `cargo clippy -p prometeu-system -p prometeu-firmware -p prometeu-host-desktop-winit --all-targets -- -D warnings`
## Affected Artifacts
- `crates/console/prometeu-firmware/src/firmware/firmware.rs`
- `crates/console/prometeu-system/src/services/game_library.rs`
- `test-cartridges/dummy-boy`
- Host/render test utilities if needed

View File

@ -0,0 +1,93 @@
---
id: PLN-0162
ticket: system-os-cartridge-switch-orchestrator
title: Specify Game Switch Contract And Direct Boot Separation
status: open
created: 2026-07-05
ref_decisions: [DEC-0039]
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Briefing
DEC-0039 must be reflected in the canonical runtime specs after the operational
contract is implemented or alongside implementation. The spec must distinguish
same-Game resume, Game replacement under SystemOS, and direct boot/debug boot.
## Objective
Update the canonical runtime documentation to describe SystemOS Game cartridge
switching and to keep direct boot/debug boot separate from Home/Hub-driven Game
replacement.
## Dependencies
- Source decision: DEC-0039.
- Can be implemented before code if the spec is written as intended behavior.
- Should be reconciled after PLN-0157 through PLN-0161 if implementation names
differ from initial plan names.
## Scope
- Update relevant files under `docs/specs/runtime/`, especially:
- `12-firmware-pos-and-prometeuhub.md`;
- `13-cartridge.md`;
- `14-boot-profiles.md`;
- `09-events-and-concurrency.md` if lifecycle events need mention;
- `10-debug-inspection-and-profiling.md` if debugger separation needs note.
- Document:
- SystemOS authority for Game switching;
- destructive replacement semantics;
- optional non-blocking terminate/save event;
- fresh VM session for new Game;
- failed switch recovery to Home/Hub;
- direct boot/debug boot separation;
- test cartridge evidence requirement.
## Non-Goals
- Do not document `.pmc` or final catalog UX as required.
- Do not specify background execution.
- Do not revise DEC-0037 or DEC-0038 semantics.
- Do not write lesson material; housekeeping will decide lessons after
execution.
## Execution Method
1. Read the runtime spec files listed in scope.
2. Add a Game switching section in the most appropriate canonical spec file.
3. Cross-reference existing Home/Hub, cartridge, boot profile, and debug boot
sections.
4. Ensure language is English and normative enough for future implementers:
`MUST`, `MUST NOT`, `MAY`, `SHOULD`.
5. Verify no non-English agenda language leaks into specs.
6. Run docs grep checks for the newly introduced terms.
## Acceptance Criteria
- Specs explicitly distinguish:
- same-Game pause/resume;
- Game A to Game B destructive replacement;
- direct boot/debug boot.
- Specs state that SystemOS owns Game switching policy.
- Specs state that a new Game gets a fresh VM session.
- Specs state that failed switch returns Home/Hub and does not restore the old
Game in v1.
- Specs mention Dummy Boy or equivalent two-cartridge evidence only as test
evidence, not as runtime feature.
- Documentation is English.
## Tests
- `rg -n "Game switch|destructive replacement|direct boot|Dummy Boy|VM session" docs/specs/runtime`
- `discussion validate`
- Run code tests only if this plan is implemented together with code changes:
`cargo test -p prometeu-system -p prometeu-firmware`
## Affected Artifacts
- `docs/specs/runtime/12-firmware-pos-and-prometeuhub.md`
- `docs/specs/runtime/13-cartridge.md`
- `docs/specs/runtime/14-boot-profiles.md`
- `docs/specs/runtime/09-events-and-concurrency.md`
- `docs/specs/runtime/10-debug-inspection-and-profiling.md`