dev/perf-host-desktop-frame-pacing-and-presentation #19

Merged
bquarkz merged 4 commits from dev/perf-host-desktop-frame-pacing-and-presentation into master 2026-04-20 12:19:51 +00:00
4 changed files with 2 additions and 403 deletions
Showing only changes of commit 193fe78b5e - Show all commits

View File

@ -1,4 +1,4 @@
{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":20,"PLN":37,"LSN":36,"CLSN":1}}
{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":20,"PLN":37,"LSN":37,"CLSN":1}}
{"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
@ -12,7 +12,7 @@
{"type":"discussion","id":"DSC-0007","status":"open","ticket":"app-home-filesystem-surface-and-semantics","title":"Agenda - App Home Filesystem Surface and Semantics","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0006","file":"workflow/agendas/AGD-0006-app-home-filesystem-surface-and-semantics.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"perf-runtime-telemetry-hot-path","title":"Agenda - [PERF] Runtime Telemetry Hot Path","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[{"id":"AGD-0007","file":"workflow/agendas/AGD-0007-perf-runtime-telemetry-hot-path.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0005","file":"workflow/decisions/DEC-0005-perf-push-based-telemetry-model.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0005","file":"workflow/plans/PLN-0005-perf-push-based-telemetry-implementation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0026","file":"lessons/DSC-0008-perf-runtime-telemetry-hot-path/LSN-0026-push-based-telemetry-model.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"perf-async-background-work-lanes-for-assets-and-fs","title":"Agenda - [PERF] Async Background Work Lanes for Assets and FS","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0008","file":"workflow/agendas/AGD-0008-perf-async-background-work-lanes-for-assets-and-fs.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0010","status":"in_progress","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-04-20","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"in_progress","created_at":"2026-03-27","updated_at":"2026-04-20"}],"decisions":[{"id":"DEC-0019","file":"DEC-0019-host-desktop-frame-pacing-and-presentation.md","status":"accepted","created_at":"2026-04-20","updated_at":"2026-04-20","ref_agenda":"AGD-0009"}],"plans":[{"id":"PLN-0036","file":"PLN-0036-host-desktop-frame-pacing-and-presentation.md","status":"done","created_at":"2026-04-20","updated_at":"2026-04-20","ref_decisions":["DEC-0019"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0010","status":"done","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-04-20","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0036","file":"lessons/DSC-0010-perf-host-desktop-frame-pacing-and-presentation/LSN-0036-frame-publication-and-host-invalidation-must-be-separate.md","status":"done","created_at":"2026-04-20","updated_at":"2026-04-20"}]}
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"perf-gfx-render-pipeline-and-dirty-regions","title":"Agenda - [PERF] GFX Render Pipeline and Dirty Regions","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0010","file":"workflow/agendas/AGD-0010-perf-gfx-render-pipeline-and-dirty-regions.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0012","status":"done","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-04-19","tags":["perf","runtime","syscall","telemetry","debug","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"lessons/DSC-0012-perf-runtime-introspection-syscalls/LSN-0034-host-owned-debug-boundaries.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19"}]}
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}

View File

@ -1,90 +0,0 @@
---
id: AGD-0009
ticket: perf-host-desktop-frame-pacing-and-presentation
title: Agenda - [PERF] Host Desktop Frame Pacing and Presentation
status: in_progress
created: 2026-03-27
resolved: 2026-04-20
decision: DEC-0019
tags: []
---
# Agenda - [PERF] Host Desktop Frame Pacing and Presentation
## Problema
O host desktop ainda roda em modo agressivo de polling e apresentacao continua.
Hoje o loop usa `ControlFlow::Poll`, pede redraw incondicionalmente e converte o framebuffer inteiro de RGB565 para RGBA8 a cada `RedrawRequested`, mesmo quando nao ha novo frame logico.
## Dor
- CPU fica ocupada sem ganho visual.
- port de referencia no desktop mascara problemas de pacing em hardware barato.
- a conta de energia/temperatura piora mesmo quando a VM esta ociosa.
## Hotspots Atuais
- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs#L252)
- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs#L270)
- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs#L390)
## Alvo da Discussao
Fechar uma politica de pacing/apresentacao host-driven que nao desperdice CPU quando nao existe frame novo.
## O Que Precisa Ser Definido
1. Gatilho de redraw.
Decidir se redraw acontece:
- apenas com logical frame pronto;
- por deadline de vsync;
- por dirty flag do front buffer;
- por evento externo relevante.
2. Politica do event loop.
Decidir entre:
- `Wait`;
- `WaitUntil`;
- `Poll` apenas em modo debug/profiling.
3. Conversao de framebuffer.
Definir se a conversao RGB565 -> RGBA8:
- continua full-frame;
- passa a ser dirty-region;
- sai da CPU e vai para shader/path especifico do host.
4. Modo ocioso.
Delimitar comportamento quando VM esta pausada, em breakpoint ou sem cart.
## Open Questions de Arquitetura
1. O host desktop deve ser referencia conservadora de energia ou apenas shell de desenvolvimento?
R: O desktop eh shell de desenvolvimento, mas pode tb ser usado para jogar em um pc. Deve oferecer controle de energia como um handheld, especialmente para desenvolvimento.
2. O runtime precisa expor um sinal explicito de "novo frame disponivel" para o host?
R: Atualmente fazemos o swap do buffer somente quando o frame logico eh pronto, esse eh o "ponto de entrada" para o host. Eh ali que a conversao de RGB565 -> RGBA8 pode ser realizada e mostrada. Se o host precisar saber quando o frame eh pronto, pode ser exposto por um sinal explicito.
3. Existe necessidade real de redraw continuo quando o overlay esta desligado?
R: Nao
## Perguntas em Aberto
Nenhuma. As perguntas de arquitetura desta agenda foram respondidas e o tema esta pronto para cristalizacao em decisao.
## Resolucao
A agenda fecha com a direcao de que o host desktop nao deve manter redraw continuo por padrao. O host deve operar com pacing orientado por frame logico pronto e por eventos externos relevantes, preservando um comportamento energeticamente conservador sem perder utilidade como shell de desenvolvimento. Se o host precisar consumir esse momento de forma explicita, o runtime pode expor um sinal canonico de "novo frame disponivel" no ponto em que o frame logico eh concluido.
## Dependencias
- `../specs/01-time-model-and-cycles.md`
- `../specs/10-debug-inspection-and-profiling.md`
- `../specs/11-portability-and-cross-platform-execution.md`
## Criterio de Saida Desta Agenda
Pode virar PR quando houver decisao escrita sobre:
- politica de control flow do host;
- criterio canonico de redraw;
- estrategia de conversao/apresentacao de framebuffer;
- comportamento de idle/pause/debug.

View File

@ -1,141 +0,0 @@
---
id: DEC-0019
ticket: perf-host-desktop-frame-pacing-and-presentation
title: Decision - [PERF] Host Desktop Frame Pacing and Presentation
status: accepted
created: 2026-04-20
accepted: 2026-04-20
agenda: AGD-0009
plans: [PLN-0036]
tags: [perf, host, desktop, frame-pacing, presentation, debug]
---
# Status
Accepted. This decision is now normatively locked and is ready to drive planning and execution.
## Contexto
O host desktop atual usa `ControlFlow::Poll`, pede redraw continuamente e reapresenta o framebuffer mesmo quando a maquina nao publicou um novo frame logico.
Esse comportamento conflita com o modelo temporal de `docs/specs/runtime/01-time-model-and-cycles.md`, onde a maquina opera em frames logicos de 60 Hz, e com o contrato de portabilidade e isolamento de debug em `docs/specs/runtime/10-debug-inspection-and-profiling.md` e `docs/specs/runtime/11-portability-and-cross-platform-execution.md`, onde apresentacao e overlay pertencem ao host, mas nao devem redefinir a semantica logica da maquina.
O problema a ser fechado aqui nao eh o desenho final do backend grafico. O problema eh definir quando o host desktop tem permissao para acordar, converter e apresentar pixels sem transformar a shell desktop em um loop de polling agressivo.
## Decisao
O host desktop SHALL adotar pacing orientado por frame logico publicado e por eventos externos relevantes, e MUST NOT manter redraw continuo por padrao.
Normas desta decisao:
1. Gatilho canonico de redraw
- O host MUST considerar um novo frame logico publicado como gatilho principal de apresentacao.
- O host MAY solicitar redraw adicional quando houver evento externo relevante que altere apenas a superficie host-owned, incluindo resize da janela, expose/invalidate da janela, toggle de overlay, atualizacao visivel do debugger ou mudanca de estado local da shell.
- O host MUST NOT solicitar redraw continuo apenas para "ver se existe frame novo".
2. Politica do event loop
- O host desktop MUST sair de `ControlFlow::Poll` como politica padrao.
- O event loop SHOULD operar em modo de espera dirigida por deadline ou evento, usando `WaitUntil` para o proximo slice logico quando houver trabalho temporal agendado e `Wait` quando nao houver deadline imediato.
- `Poll` MAY existir apenas em modo explicitamente opt-in de profiling/diagnostico host-owned e MUST NOT ser o comportamento normal de execucao.
3. Conversao de framebuffer
- A conversao RGB565 -> RGBA8 permanece full-frame nesta fase.
- Essa conversao MUST acontecer apenas quando houver novo frame logico publicado ou quando um evento host-owned exigir recomposicao/apresentacao da superficie visivel.
- Dirty-region conversion e offload para shader/GPU ficam explicitamente fora do contrato desta decisao e poderao ser avaliados em discussao separada se o full-frame on-demand ainda for insuficiente.
4. Modo ocioso, pausa e debug
- Quando a VM estiver pausada, em breakpoint, esperando `start`, ou sem cart carregado, o host MUST preservar o ultimo frame visivel valido e MUST NOT ficar redesenhando continuamente.
- Nesses estados, redraw adicional so pode ocorrer por evento host-owned relevante, como overlay/debug data visivel, resize/expose ou transicao explicita de estado.
- Buffers logicos da maquina MUST NOT ser trocados durante pausa apenas para sustentar HUD host-owned.
5. Sinal de "novo frame disponivel"
- O runtime/host boundary MUST ter um ponto canonico de observacao do "frame pronto", alinhado ao momento em que o frame logico e publicado para apresentacao.
- A implementacao inicial MAY usar um sinal explicito, contador monotonicamente crescente, dirty flag ou observacao do ponto de swap/publicacao, desde que a semantica seja unica e nao ambigua.
- Essa decisao MUST NOT introduzir uma ABI guest-visible nova. O sinal pertence ao boundary interno runtime-host e as superficies host-owned de inspecao.
## Rationale
`Poll` com redraw continuo mascara custo de apresentacao, consome CPU sem beneficio visual e reduz a utilidade do desktop como referencia de comportamento energetico razoavel.
Ao mesmo tempo, a shell desktop nao deve ser tratada como uma plataforma "ultra-conservadora" a ponto de perder ergonomia de debug. Por isso a decisao nao proibe redraw extra; ela apenas restringe redraw extra a eventos com causa concreta e visivel.
Manter a conversao full-frame por enquanto evita reabrir a arquitetura de renderizacao durante um trabalho cujo alvo principal eh pacing. O ganho imediato vem de parar de converter e apresentar quando nada mudou. Se isso nao bastar, dirty regions ou shader path podem ser discutidos depois com evidencias.
Separar "frame logico publicado" de "overlay host-owned mudou" preserva o contrato de portabilidade: o host pode mostrar mais informacao tecnica sem forcar a VM a produzir frames adicionais nem adulterar o framebuffer logico.
## Invariantes / Contrato
- A maquina continua definindo frames logicos em 60 Hz; o host nao redefine esse relogio.
- O host apresenta o ultimo frame logico publicado; ele nao inventa frames intermediarios.
- Overlay e debugger sao host-owned e MAY compor sobre uma superficie de apresentacao host-only.
- Overlay/debug MUST NOT exigir redraw continuo quando seu conteudo estiver estavel.
- Conversao/presentacao do framebuffer MUST ser dirigida por mudanca observavel, nao por polling agressivo.
- O boundary runtime-host MUST expor um criterio unico para detectar publicacao de frame logico.
- Esta decisao nao promove dirty regions nem GPU offload a contrato normativo.
- Esta decisao nao altera semantica guest-visible de `DRAW`, buffers logicos, ciclos, ou telemetria de certificacao.
## Alternativas Descartadas
### Manter `Poll` permanente no desktop
Descartado porque esconde custo real de apresentacao, desperdiça CPU e cria uma shell cuja estabilidade aparente depende de trabalho inutil.
### Redraw orientado apenas por vsync fisico
Descartado como contrato canonico porque o modelo PROMETEU e dirigido por frame logico e a portabilidade nao depende de sincronizar a semantica da maquina a uma frequencia fisica do host.
### Reabrir o problema com dirty regions ou shader path como pre-condicao
Descartado nesta etapa porque mistura otimizacao secundaria com o contrato principal de pacing. O problema imediato pode e deve ser resolvido sem nova arquitetura de render backend.
## Impactos
### Spec
- `docs/specs/runtime/10-debug-inspection-and-profiling.md` deve refletir que a apresentacao host-owned observa frame publicado e nao requer redraw continuo para HUD/overlay estavel.
- `docs/specs/runtime/11-portability-and-cross-platform-execution.md` deve explicitar que a superficie host de apresentacao pode recompor overlay por evento relevante, sem transformar isso em polling permanente.
### Runtime
- O runtime pode precisar expor ou estabilizar um ponto interno de publicacao de frame pronto para o host desktop consumir de forma canonica.
- Nenhuma nova ABI guest-visible deve ser criada por este trabalho.
### Host Desktop
- O loop winit deve migrar de `Poll` para espera dirigida por deadline/evento.
- `request_redraw()` deixa de ser incondicional no ciclo de idle.
- A apresentacao passa a depender de novo frame logico ou evento host-owned relevante.
### Firmware
- Sem mudanca de semantica guest-visible.
- Estados de pausa/breakpoint continuam impedindo avanco de tempo logico e swap de buffers logicos.
### Tooling
- Overlay/debugger continuam host-owned, mas precisam declarar quando realmente invalidam a superficie visivel.
- Profiling host-only pode manter um modo opt-in de polling agressivo, separado do comportamento normal.
## Referencias
- [AGD-0009](</Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/discussion/workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md>)
- [docs/specs/runtime/01-time-model-and-cycles.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/01-time-model-and-cycles.md)
- [docs/specs/runtime/10-debug-inspection-and-profiling.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/10-debug-inspection-and-profiling.md)
- [docs/specs/runtime/11-portability-and-cross-platform-execution.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/11-portability-and-cross-platform-execution.md)
- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs:252)
## Propagacao Necessaria
- Escrever um `PLN` para implementar a mudanca no host desktop.
- Atualizar as specs normativas citadas para refletir este contrato.
- Ajustar o host desktop para consumir um gatilho canonico de frame publicado.
- Adicionar testes para:
- ausencia de redraw continuo sem frame novo;
- redraw em evento host-owned relevante;
- preservacao do ultimo frame em pausa/breakpoint/no-cart;
- modo opt-in de polling apenas quando explicitamente habilitado.
## Revision Log
- 2026-04-20: Initial draft from AGD-0009.
- 2026-04-20: Accepted and linked to PLN-0036.

View File

@ -1,170 +0,0 @@
---
id: PLN-0036
ticket: perf-host-desktop-frame-pacing-and-presentation
title: Plan - Host Desktop Frame Pacing and Presentation
status: done
created: 2026-04-20
completed: 2026-04-20
tags: [perf, host, desktop, frame-pacing, presentation, debug]
---
## Briefing
Implement `DEC-0019` by removing unconditional desktop redraw polling, introducing a canonical host-side frame-publication trigger, preserving the last visible frame during paused or idle states, and updating the normative specs to reflect the locked contract.
## Decisions de Origem
- `DEC-0019` - Host Desktop Frame Pacing and Presentation
## Alvo
Deliver a host desktop execution path where:
- the winit loop no longer uses continuous polling by default;
- redraw happens only after logical frame publication or explicit host-owned invalidation events;
- RGB565 to RGBA8 conversion remains full-frame but only runs on demand;
- paused, debugger-waiting, and no-cartridge states keep the last valid image without continuous redraw;
- specs and tests match the accepted decision.
## Escopo
- Update the desktop host loop in `crates/host/prometeu-host-desktop-winit/src/runner.rs`.
- Introduce or stabilize a canonical "new frame published" signal at the runtime-host boundary.
- Track host-owned invalidation causes for overlay, debugger, and window events.
- Update the relevant runtime specs under `docs/specs/runtime/`.
- Add or extend automated tests for redraw gating and paused-state behavior.
## Fora de Escopo
- Dirty-region framebuffer conversion.
- GPU/shader-based presentation paths.
- New guest-visible ABI or debug surface.
- Redesign of overlay visuals or debugger protocol beyond invalidation signaling.
- Reopening the architecture covered by `DEC-0019`.
## Plano de Execucao
### Step 1 - Establish the canonical frame-publication trigger
**What:** Define the single host-consumable signal that indicates a new logical frame has been published.
**How:** Inspect the current buffer swap/publication point in the desktop runtime path and choose the existing internal publication event, dirty flag, or monotonic frame counter that can become the canonical trigger required by `DEC-0019`. If no stable signal exists, add a host-internal publication marker that changes exactly once per newly published logical frame and is not guest-visible.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- any directly related runtime/firmware module discovered as the current frame-publication owner
**Depends on:** none
### Step 2 - Replace unconditional redraw requests with invalidation-driven scheduling
**What:** Remove the unconditional redraw call from the idle loop and gate presentation on frame publication or host-owned invalidation.
**How:** Refactor `about_to_wait()` and redraw scheduling in `runner.rs` so the host requests redraw only when:
- a new logical frame was published since the last presentation;
- the window receives a visible invalidation event such as resize/expose;
- overlay state toggles or changes a visible host-owned layer;
- debugger-visible state changes require host-side recomposition.
Introduce explicit host-owned invalidation state if needed so redraw causes are tracked instead of inferred by polling.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
**Depends on:** Step 1
### Step 3 - Move the event loop from default `Poll` to deadline/event waiting
**What:** Change the normal desktop control flow so the host waits for the next logical deadline or external event instead of spinning continuously.
**How:** Update `resumed()` and any related loop control code in `runner.rs` to stop using `ControlFlow::Poll` as the default. Use `WaitUntil` when a next logical tick deadline is known and `Wait` when the host is effectively idle with no immediate timing deadline. Keep any aggressive polling path behind an explicit profiling-only switch rather than as baseline behavior.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/main.rs` if a profiling-only opt-in flag is wired at startup
**Depends on:** Step 2
### Step 4 - Preserve the last valid frame during paused, breakpoint, and no-cart states
**What:** Ensure non-running machine states do not cause repeated conversion/presentation work while still allowing host-owned UI recomposition when something visible changes.
**How:** Separate "machine produced a new frame" from "host-owned layer needs redraw". Keep the last presented RGBA output available for reuse, avoid logical buffer swaps during pause-only overlay activity, and ensure debugger waiting and no-cartridge states do not schedule continuous redraws. If overlay or debugger content changes while the machine is paused, redraw only the host-owned composition layer on explicit invalidation.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs`
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs`
**Depends on:** Step 2
### Step 5 - Update the normative specs
**What:** Propagate the accepted decision into the canonical runtime specs.
**How:** Update the portability and debug chapters so they explicitly state that desktop presentation observes published logical frames, that host-owned overlay/debug redraw is event-driven rather than continuously polled, and that stable host HUD state does not justify perpetual redraw. Keep the text aligned with the locked decision and do not introduce new architecture.
**File(s):**
- `docs/specs/runtime/10-debug-inspection-and-profiling.md`
- `docs/specs/runtime/11-portability-and-cross-platform-execution.md`
**Depends on:** Step 1
### Step 6 - Add regression tests and evidence
**What:** Add automated coverage for the redraw contract and document manual evidence where platform events are hard to model.
**How:** Extend or add tests in the desktop host crate to cover:
- no redraw request when no new frame and no host invalidation occurred;
- redraw request after a newly published logical frame;
- redraw request after overlay toggle or equivalent host-owned invalidation;
- no continuous redraw in paused/debugger-waiting/no-cart states;
- preservation of last visible frame semantics while paused.
Where direct winit event simulation is difficult, factor logic into testable state transitions and keep any remaining platform verification in a short manual checklist.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs` if overlay invalidation helpers become testable
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs` if debugger invalidation hooks are exposed
**Depends on:** Steps 2, 3, 4
## Criterios de Aceite
- The default desktop event loop no longer runs in continuous `ControlFlow::Poll`.
- The host requests redraw only after canonical frame publication or explicit host-owned invalidation.
- Full-frame RGB565 to RGBA8 conversion remains in place but is not executed continuously while the visible machine frame is unchanged.
- Paused, breakpoint, debugger-waiting, and no-cartridge states preserve the last valid image without continuous redraw.
- Overlay or debugger changes can still trigger targeted host-owned redraw when visually necessary.
- No guest-visible ABI is added for this feature.
- The relevant runtime specs state the same redraw and presentation contract as `DEC-0019`.
- Automated tests cover the main redraw gating paths and paused-state behavior.
## Tests / Validacao
### Unit Tests
- Add focused tests for redraw scheduling state transitions in the desktop host runner.
- Add tests for any helper that tracks frame-publication state or host-owned invalidation causes.
### Integration Tests
- Extend host crate tests to verify frame publication and debugger/overlay invalidation do not regress redraw policy.
- Run `cargo test -p prometeu-host-desktop-winit --lib`.
### Manual Verification
- Launch the desktop host with overlay disabled and confirm CPU usage drops when the machine is visually stable.
- Toggle overlay on and off and confirm redraw happens on the visible transition without restoring continuous polling.
- Pause execution or wait for debugger start and confirm the last frame remains visible without repeated redraw.
- Resize or expose the window and confirm the surface is recomposed correctly.
## Riscos
- The actual frame-publication point may be less explicit than assumed, requiring a small host-internal contract addition before redraw gating can be made reliable.
- winit waiting semantics can introduce timing regressions if the next logical deadline is computed incorrectly.
- Overlay or debugger code may currently assume redraw is always free, which can surface hidden invalidation bugs after polling is removed.
- Manual verification may still be needed for some window-system invalidation behavior that is cumbersome to model in tests.