14 KiB
| id | ticket | title | status | created | resolved | decision | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AGD-0035 | task-owned-shell-windows | Agenda - Task-Owned Shell Windows | accepted | 2026-05-15 | 2026-05-15 | DEC-0027 |
|
Agenda - Task-Owned Shell Windows
Contexto
O Prometeu OS ja possui SystemOS como autoridade semantica para coordenar
lifecycle entre Task e Process, com facades por dominio para evitar que o
firmware manipule storage interno diretamente.
O modelo atual separa:
Process = execucao tecnica
Task = presenca navegavel
Window = presenca visual da task
O WindowOwner ja representa Hub, Task(TaskId) e Overlay. Shell apps ja
conseguem criar janelas associadas a uma task, e games continuam fora do
WindowManager: eles sao sessoes fullscreen conduzidas por GameRunningStep,
nao janelas.
Hoje, porem, ShellRunningStep ainda decide se continua rodando a partir de um
sinal generico: focused_window_active. Esse sinal vem do resultado do update
do Hub e apenas indica se existe alguma janela focada/ativa, sem confirmar que
essa janela pertence a task que o ShellRunningStep esta conduzindo.
Problema
O contrato de liveness de uma Shell task ainda esta acoplado a presenca visual generica, nao a presenca visual da propria task.
Isso deixa uma lacuna conceitual:
- uma task pode estar em
Foreground, mas a janela focada pode pertencer a outro owner; - uma janela pode estar focada, mas nao representar a task que esta rodando no
ShellRunningStep; - o firmware precisa inferir continuidade por um booleano generico em vez de perguntar ao OS: "esta task ainda possui uma janela ativa/focada?".
Se Task e a unidade de navegacao, e Window e a presenca visual dessa task,
o fluxo de Shell precisa saber se a presenca visual pertence a mesma task.
Pontos Criticos
-
Autoridade do contrato. A pergunta deve provavelmente passar por
SystemOSou por uma facade de windows/lifecycle, nao por logica espalhada no Hub. OWindowManagerpode armazenar e consultar janelas, mas a semantica de "task continua viva" deve permanecer coerente com o modelo de lifecycle. -
Foco versus atividade. A decisao precisa separar:
- "a task possui alguma janela";
- "a task possui uma janela ativa";
- "a task possui a janela atualmente focada".
Para o
ShellRunningStep, o criterio candidato e mais forte: a janela focada deve pertencer a propria task. -
Encerramento da task. Se uma Shell task perde sua unica janela ativa/focada, o sistema precisa decidir se isso fecha a task, suspende a task, retorna ao Hub, ou representa erro. Para esta agenda, o foco e o contrato Task-Window; politicas futuras de background ficam fora.
-
Separacao entre Shell e Game. Games nao devem virar
WindowOwner::Task. A presenca visual de game continua sendo a propria sessao fullscreen doGameRunningStep. O contrato aqui vale para Shell/system apps representados por janelas. -
Multiplicidade futura sem resolver agora. O contrato deve ser simples o bastante para uma janela por Shell task hoje, mas nao deve bloquear uma evolucao posterior para multiplas janelas. A agenda nao deve decidir dock, app switcher, services em background, minimizacao, ou redesign da Shell.
Opcoes
Opcao A - Manter focused_window_active como criterio generico
Abordagem: ShellRunningStep continua dependendo do outcome generico do
Hub, que informa apenas se existe alguma janela focada/ativa.
Vantagens:
- menor mudanca imediata;
- preserva o fluxo atual de retorno ao Hub;
- evita adicionar API nova no
WindowManageragora.
Riscos / Custos:
- nao expressa o modelo
Task = presenca navegaveleWindow = presenca visual da task; - permite continuidade baseada em janela de outro owner;
- mantem uma inferencia de lifecycle fora do contrato direto do OS;
- tende a piorar quando houver mais janelas ou owners.
Leitura: opcao aceitavel apenas como estado transitorio, nao como contrato final.
Opcao B - ShellRunningStep depende de janela focada pertencente a propria task
Abordagem: expor uma consulta do tipo
focused_window_belongs_to_task(task_id) ou
task_has_focused_window(task_id). O ShellRunningStep continua somente se a
task estiver Foreground e a janela focada tiver WindowOwner::Task(task_id).
Vantagens:
- alinha diretamente
TaskeWindow; - remove a ambiguidade do booleano generico;
- torna o encerramento de Shell task explicavel: sem janela focada da propria task, nao ha presenca visual ativa para aquela task;
- funciona bem para o modelo atual de uma Shell task em foreground.
Riscos / Custos:
- pode ser forte demais se o futuro permitir task com janela existente mas temporariamente sem foco;
- exige definir se perda de foco para
HubouOverlayfecha a task ou apenas pausa o fluxo; - precisa tomar cuidado para overlays nao roubarem foco de forma que fechem a task acidentalmente.
Leitura: e a opcao mais coerente para o contrato imediato, desde que overlays e Hub sejam tratados explicitamente.
Opcao C - ShellRunningStep depende de qualquer janela ativa pertencente a propria task
Abordagem: expor uma consulta do tipo task_has_active_window(task_id).
Foco global continua separado: a task segue viva enquanto pelo menos uma janela
aberta/ativa pertence a ela, mesmo que outra superficie esteja focada.
Vantagens:
- prepara melhor um futuro com overlays, app switcher ou multiplas janelas;
- evita fechar task por perda temporaria de foco;
- separa "existencia visual da task" de "janela no topo".
Riscos / Custos:
- exige definir imediatamente o que significa "active" alem de
has_focus; - pode preservar tasks sem presenca navegavel real se a janela existir mas nao estiver selecionada;
- abre portas para semantica de background/minimizacao, que esta fora do escopo desta agenda.
Leitura: boa direcao futura, mas talvez maior que o contrato necessario agora.
Opcao D - Lifecycle fecha janelas; janelas nunca fecham lifecycle
Abordagem: ShellRunningStep ignora foco/janelas para continuidade; a task
so fecha quando o lifecycle manda fechar. O WindowManager seria apenas
reflexo visual da task, nao sinal de liveness.
Vantagens:
- preserva autoridade total do lifecycle;
- evita que bugs de foco encerrem task;
- simples de raciocinar em termos de
TaskState.
Riscos / Custos:
- contradiz a intencao de
Window = presenca visual da taskpara Shell apps; - pode manter uma Shell task foreground sem janela visivel;
- empurra para outro mecanismo a deteccao de fechamento pelo usuario.
Leitura: defensavel para services/background no futuro, mas desalinhada com Shell apps visuais neste escopo.
Sugestao / Recomendacao
A recomendacao consolidada e seguir a Opcao B como contrato v1:
ShellRunningStep continua somente quando:
1. sua Task esta em Foreground;
2. a janela focada pertence a WindowOwner::Task(task_id) da propria task.
Isso troca o sinal generico focused_window_active por uma pergunta explicita
ao WindowFacade:
os.windows().focused_window_belongs_to_task(task_id)
Esse nome comunica que o WindowManager possui um foco global, e que a
pergunta e se esse foco global pertence a task informada. O nome
task_has_focused_window continua sendo conceitualmente aceitavel, mas pode
soar como se cada task tivesse um foco proprio.
O comportamento v1 recomendado e:
if !ctx.os.windows().focused_window_belongs_to_task(self.task_id) {
ctx.os.lifecycle().close_task(self.task_id)?;
return Some(FirmwareState::HubHome(HubHomeStep));
}
O contrato deve declarar tambem:
HubeOverlaynao sao Shell task windows;- games nao entram no
WindowManager; - a ausencia de janela focada da propria Shell task fecha ou encerra o fluxo da Shell task conforme a politica atual, sem introduzir background service ou minimizacao nesta decisao;
- multiplas janelas, dock, app switcher, background services e redesign da Shell ficam fora desta agenda.
Perguntas em Aberto
- O criterio v1 deve ser "janela focada pertence a task" ou "task possui alguma janela ativa"?
- O nome da API deve falar em foco (
task_has_focused_window) ou em pertencimento do foco global (focused_window_belongs_to_task)? - Quando uma
Overlayesta focada, ela deve preservar a Shell task subjacente ou isso ainda nao existe no modelo atual? - Fechar a ultima janela da Shell task deve chamar
close_task(task_id)diretamente ou apenas retornar ao Hub e deixar lifecycle resolver? - A consulta deve morar no
WindowFacade, em uma facade de lifecycle, ou em uma facade composta deSystemOS? - A decision posterior precisa alterar somente firmware/system, ou tambem documentar esse contrato nos specs canonicos?
Respostas Consolidadas
Criterio v1
O criterio v1 e "janela focada pertence a task".
ShellRunningStep continua somente quando:
TaskState::Foreground
+
focused window owner == WindowOwner::Task(task_id)
A alternativa "task possui alguma janela ativa" fica reservada para um futuro com overlays, multiplas janelas, minimizacao ou app switcher. Ela e mais ampla do que o contrato necessario agora.
Nesta versao, Shell apps sao foreground e visualmente representados por uma janela focada. Se a janela focada nao pertence a task, a task nao deve continuar executando.
Nome e local da API
O nome recomendado e:
focused_window_belongs_to_task(task_id)
A API deve morar em WindowFacade:
os.windows().focused_window_belongs_to_task(task_id)
Motivo: a pergunta e sobre foco, janela e WindowOwner, nao sobre transicao de
lifecycle.
A separacao de responsabilidades fica:
WindowFacade
responde perguntas sobre janelas, foco e ownership
LifecycleFacade
altera TaskState e ProcessState
ShellRunningStep
coordena a decisao firmware-level entre janela e lifecycle
Se esse padrao se repetir, uma facade composta como sessions() pode surgir no
futuro, mas ela nao e necessaria para este contrato v1.
Overlays
Overlay policy ainda nao existe no modelo atual.
Para v1:
Hub nao e janela da task.
Overlay nao e janela da task.
Game nao e WindowManager window.
ShellRunningStep exige foco em WindowOwner::Task(task_id).
Se uma overlay puder roubar foco, isso precisa ser tratado em uma agenda propria de overlay/modal policy. Esta decisao nao deve tentar preservar, pausar, ou modelar Shell task sob overlay.
Possiveis direcoes futuras, fora deste escopo:
- overlay modal preserva a task subjacente;
- overlay nao-modal nao rouba foco;
- overlay possui owner/contexto proprio.
Fechamento da Shell task
Quando a Shell task perde sua janela focada elegivel, o firmware deve chamar:
os.lifecycle().close_task(task_id)
e entao retornar para HubHome.
Nao basta apenas retornar ao Hub, porque isso deixaria task/processo dependente de cleanup implicito.
Contrato v1:
Shell task perde sua janela focada elegivel
-> lifecycle.close_task(task_id)
-> TaskState::Closed
-> ProcessState::Stopped
-> FirmwareState::HubHome
O fechamento visual da Shell task precisa passar pelo lifecycle do SystemOS.
Propagacao para specs
A decision posterior deve alterar firmware/system e tambem documentar o contrato nos specs canonicos.
O contrato arquitetural a preservar e:
Process = execucao tecnica
Task = presenca navegavel
Window = presenca visual da task
Tambem deve ficar documentado:
- games nao sao janelas;
- games rodam como sessoes fullscreen via
GameRunningStep; - Shell apps possuem janelas no
WindowManager; - Shell app windows usam
WindowOwner::Task(TaskId); HubeOverlaynao sao janelas de Shell task;- na v1,
ShellRunningStepso continua se a janela focada pertence a sua propria task.
Isso evita que trabalho futuro transforme game em window ou reintroduza
focused_window_active como contrato generico.
Fora de Escopo
- dock;
- app switcher;
- background services;
- minimizacao;
- multiplas janelas complexas;
- redesign da Shell;
- transformar games em janelas;
- mudar o modelo fullscreen de
GameRunningStep; - reabrir o contrato geral de
Process,Taske lifecycle ja consolidado.
Criterio para Encerrar
Esta agenda pode virar decision quando houver resposta explicita para:
- qual predicado
ShellRunningStepusa para continuar; - onde a API de consulta Task-Window mora;
- como
Hub,OverlayeGameRunningStepficam excluidos ou tratados; - qual comportamento ocorre quando a Shell task perde sua janela elegivel;
- quais specs ou codigos precisam ser propagados depois da decision.
Discussion
A discussao convergiu para um contrato v1 pequeno, focado em Shell task foreground com janela focada propria.
Resumo da direcao:
AGD-0035 segue a Opcao B.
Predicado:
focused_window_belongs_to_task(task_id)
Facade:
os.windows()
Comportamento:
se falso em ShellRunningStep:
os.lifecycle().close_task(task_id)
retorna HubHome
Fora de escopo:
overlay policy
background
minimizacao
app switcher
game windows
Casos de background, overlay policy, minimizacao, app switcher e multiplas janelas devem ficar para agendas futuras.
Resolution
Aceita em 2026-05-15 e promovida para DEC-0027.
A decision deve seguir a Opcao B: ShellRunningStep continua somente quando a
Shell task esta em TaskState::Foreground e a janela focada pertence a
WindowOwner::Task(task_id). A API normativa e
os.windows().focused_window_belongs_to_task(task_id). Quando o predicado for
falso, ShellRunningStep deve fechar a task via
os.lifecycle().close_task(task_id) e retornar HubHome.