housekeeping
This commit is contained in:
parent
c2698e6a22
commit
82a3380426
@ -1,5 +1,5 @@
|
||||
{"type":"meta","next_id":{"DSC":36,"AGD":36,"DEC":28,"PLN":62,"LSN":44,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0035","status":"in_progress","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-agenda-task-owned-shell-windows.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15"}],"decisions":[{"id":"DEC-0027","file":"DEC-0027-decision-task-owned-shell-windows.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0059","file":"PLN-0059-plan-task-window-contract-specs.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0027"]},{"id":"PLN-0060","file":"PLN-0060-plan-focused-window-ownership-api.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0027"]},{"id":"PLN-0061","file":"PLN-0061-plan-shell-running-lifecycle-integration.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0027"]}],"lessons":[]}
|
||||
{"type":"meta","next_id":{"DSC":36,"AGD":36,"DEC":28,"PLN":62,"LSN":45,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"system-os-domain-facades","title":"Agenda - SystemOS Domain Facades","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","services","api-surface","lifecycle","fs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||
{"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":"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":"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":"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":"discussion/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":"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":"DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"discussion/lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
---
|
||||
id: LSN-0044
|
||||
ticket: task-owned-shell-windows
|
||||
title: Task Window Liveness Belongs to the Task
|
||||
created: 2026-05-15
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle]
|
||||
---
|
||||
|
||||
# Task Window Liveness Belongs to the Task
|
||||
|
||||
## Context
|
||||
|
||||
The Prometeu OS model separates execution, navigation, and visual presence:
|
||||
|
||||
```text
|
||||
Process = technical execution
|
||||
Task = navigable presence
|
||||
Window = visual presence of the task
|
||||
```
|
||||
|
||||
Before `DSC-0035`, shell execution used a generic `focused_window_active`
|
||||
signal. That signal only answered whether any window was focused. It did not
|
||||
prove that the focused window represented the shell task currently driven by
|
||||
`ShellRunningStep`.
|
||||
|
||||
The implemented contract replaced that generic signal with a task-owned window
|
||||
predicate:
|
||||
|
||||
```text
|
||||
os.windows().focused_window_belongs_to_task(task_id)
|
||||
```
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Shell liveness requires the task's own focused window
|
||||
|
||||
**What:** `ShellRunningStep` continues only when the task is foreground and the
|
||||
global focused window is owned by `WindowOwner::Task(task_id)`.
|
||||
|
||||
**Why:** A shell task in foreground must have its own visual presence. Any
|
||||
focused window is not enough; the focused window must belong to the same task.
|
||||
|
||||
**Trade-offs:** This v1 rule is strict. It does not preserve a shell task under
|
||||
focused overlays, minimized windows, background execution, or app switcher
|
||||
state. Those behaviors need their own explicit contracts.
|
||||
|
||||
### Window ownership is queried through the window facade
|
||||
|
||||
**What:** `WindowFacade` exposes
|
||||
`focused_window_belongs_to_task(task_id)`.
|
||||
|
||||
**Why:** The question is about the global focused window and its owner. It is a
|
||||
window-domain query, not a lifecycle transition.
|
||||
|
||||
**Trade-offs:** Firmware still coordinates across domains: it asks the window
|
||||
facade for ownership and then calls lifecycle when the predicate is false.
|
||||
|
||||
### Lifecycle still owns state transitions
|
||||
|
||||
**What:** When the shell task loses its eligible focused window,
|
||||
`ShellRunningStep` closes the task through `os.lifecycle().close_task(task_id)`
|
||||
before returning to `HubHome`.
|
||||
|
||||
**Why:** Returning to Hub without lifecycle closure would leave task and process
|
||||
state dependent on implicit cleanup.
|
||||
|
||||
**Trade-offs:** A visual close becomes a lifecycle event for foreground shell
|
||||
apps. That is correct for v1 shell apps, but it must not be generalized to
|
||||
background services without a separate decision.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
Use this split when OS behavior crosses services:
|
||||
|
||||
```text
|
||||
WindowFacade
|
||||
answers questions about windows, focus, and ownership
|
||||
|
||||
LifecycleFacade
|
||||
changes TaskState and ProcessState
|
||||
|
||||
Firmware step
|
||||
coordinates policy between the two domains
|
||||
```
|
||||
|
||||
The useful pattern is not "windows close tasks". The pattern is:
|
||||
|
||||
1. derive a visual-presence predicate from the window domain;
|
||||
2. let the firmware step decide what the predicate means in that state;
|
||||
3. perform lifecycle transitions through `SystemOS` lifecycle.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not use a generic "some window is focused" signal as a task liveness
|
||||
contract.
|
||||
- Do not treat `Hub` or `Overlay` windows as shell task windows.
|
||||
- Do not model game cartridges as `WindowManager` windows. Games remain
|
||||
fullscreen `GameRunningStep` sessions.
|
||||
- Do not add overlay preservation, minimization, app switcher, or background
|
||||
service behavior as incidental side effects of shell liveness.
|
||||
- Do not return to Hub without closing the shell task through lifecycle.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Task-owned shell windows bind shell liveness to the task's own visual
|
||||
presence.
|
||||
- Ownership predicates belong in the window facade; state mutation belongs in
|
||||
lifecycle.
|
||||
- Strict v1 semantics are easier to evolve than an implicit "active window"
|
||||
concept.
|
||||
- Future overlay or background behavior should be introduced by explicit
|
||||
policy, not by weakening the shell liveness predicate.
|
||||
@ -1,432 +0,0 @@
|
||||
---
|
||||
id: AGD-0035
|
||||
ticket: task-owned-shell-windows
|
||||
title: Agenda - Task-Owned Shell Windows
|
||||
status: accepted
|
||||
created: 2026-05-15
|
||||
resolved: 2026-05-15
|
||||
decision: DEC-0027
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle]
|
||||
---
|
||||
|
||||
# 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:
|
||||
|
||||
```text
|
||||
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
|
||||
|
||||
1. Autoridade do contrato.
|
||||
A pergunta deve provavelmente passar por `SystemOS` ou por uma facade de
|
||||
windows/lifecycle, nao por logica espalhada no Hub. O `WindowManager` pode
|
||||
armazenar e consultar janelas, mas a semantica de "task continua viva" deve
|
||||
permanecer coerente com o modelo de lifecycle.
|
||||
|
||||
2. 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.
|
||||
|
||||
3. 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.
|
||||
|
||||
4. Separacao entre Shell e Game.
|
||||
Games nao devem virar `WindowOwner::Task`. A presenca visual de game
|
||||
continua sendo a propria sessao fullscreen do `GameRunningStep`. O contrato
|
||||
aqui vale para Shell/system apps representados por janelas.
|
||||
|
||||
5. 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 `WindowManager` agora.
|
||||
|
||||
**Riscos / Custos:**
|
||||
|
||||
- nao expressa o modelo `Task = presenca navegavel` e `Window = 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 `Task` e `Window`;
|
||||
- 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 `Hub` ou `Overlay` fecha 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 task` para 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:
|
||||
|
||||
```text
|
||||
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`:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
- `Hub` e `Overlay` nao 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
|
||||
|
||||
- [x] O criterio v1 deve ser "janela focada pertence a task" ou "task possui
|
||||
alguma janela ativa"?
|
||||
- [x] O nome da API deve falar em foco (`task_has_focused_window`) ou em
|
||||
pertencimento do foco global (`focused_window_belongs_to_task`)?
|
||||
- [x] Quando uma `Overlay` esta focada, ela deve preservar a Shell task
|
||||
subjacente ou isso ainda nao existe no modelo atual?
|
||||
- [x] Fechar a ultima janela da Shell task deve chamar `close_task(task_id)`
|
||||
diretamente ou apenas retornar ao Hub e deixar lifecycle resolver?
|
||||
- [x] A consulta deve morar no `WindowFacade`, em uma facade de lifecycle, ou em
|
||||
uma facade composta de `SystemOS`?
|
||||
- [x] 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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
focused_window_belongs_to_task(task_id)
|
||||
```
|
||||
|
||||
A API deve morar em `WindowFacade`:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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)`;
|
||||
- `Hub` e `Overlay` nao sao janelas de Shell task;
|
||||
- na v1, `ShellRunningStep` so 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`, `Task` e lifecycle ja consolidado.
|
||||
|
||||
## Criterio para Encerrar
|
||||
|
||||
Esta agenda pode virar decision quando houver resposta explicita para:
|
||||
|
||||
1. qual predicado `ShellRunningStep` usa para continuar;
|
||||
2. onde a API de consulta Task-Window mora;
|
||||
3. como `Hub`, `Overlay` e `GameRunningStep` ficam excluidos ou tratados;
|
||||
4. qual comportamento ocorre quando a Shell task perde sua janela elegivel;
|
||||
5. 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:
|
||||
|
||||
```text
|
||||
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`.
|
||||
@ -1,238 +0,0 @@
|
||||
---
|
||||
id: DEC-0027
|
||||
ticket: task-owned-shell-windows
|
||||
title: Decision - Task-Owned Shell Windows
|
||||
status: accepted
|
||||
created: 2026-05-15
|
||||
accepted: 2026-05-15
|
||||
ref_agenda: AGD-0035
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle]
|
||||
---
|
||||
|
||||
# Decision - Task-Owned Shell Windows
|
||||
|
||||
## Status
|
||||
|
||||
Accepted on 2026-05-15. This decision is normative and ready to drive plans.
|
||||
|
||||
## Contexto
|
||||
|
||||
O Prometeu OS ja separa lifecycle tecnico e presenca navegavel:
|
||||
|
||||
```text
|
||||
Process = execucao tecnica
|
||||
Task = presenca navegavel
|
||||
Window = presenca visual da task
|
||||
```
|
||||
|
||||
`SystemOS` e a autoridade semantica para coordenar `TaskState` e
|
||||
`ProcessState`. `TaskManager`, `ProcessManager` e `WindowManager` continuam
|
||||
como storage/servicos de dominio, acessados por facades.
|
||||
|
||||
`WindowOwner` ja representa `Hub`, `Task(TaskId)` e `Overlay`. Shell apps podem
|
||||
criar janelas com `WindowOwner::Task(task_id)`. Games continuam fora do
|
||||
`WindowManager`: eles sao sessoes fullscreen conduzidas por `GameRunningStep`,
|
||||
nao janelas.
|
||||
|
||||
Antes desta decision, `ShellRunningStep` dependia de um sinal generico,
|
||||
`focused_window_active`, que apenas informava se existia alguma janela focada.
|
||||
Esse contrato nao garantia que a janela focada pertencia a task que o
|
||||
`ShellRunningStep` estava conduzindo.
|
||||
|
||||
## Decisao
|
||||
|
||||
`ShellRunningStep` MUST continuar rodando uma Shell task somente quando as duas
|
||||
condicoes abaixo forem verdadeiras:
|
||||
|
||||
```text
|
||||
TaskState::Foreground
|
||||
+
|
||||
focused window owner == WindowOwner::Task(task_id)
|
||||
```
|
||||
|
||||
O predicado de janela MUST ser exposto pela `WindowFacade` como:
|
||||
|
||||
```text
|
||||
os.windows().focused_window_belongs_to_task(task_id)
|
||||
```
|
||||
|
||||
Esse predicado MUST consultar o foco global do `WindowManager` e responder se a
|
||||
janela atualmente focada pertence a `WindowOwner::Task(task_id)`.
|
||||
|
||||
Quando `ShellRunningStep` detectar que a Shell task foreground nao possui a
|
||||
janela focada elegivel, ele MUST fechar a task por lifecycle antes de retornar
|
||||
ao Hub:
|
||||
|
||||
```text
|
||||
Shell task perde sua janela focada elegivel
|
||||
-> os.lifecycle().close_task(task_id)
|
||||
-> TaskState::Closed
|
||||
-> ProcessState::Stopped
|
||||
-> FirmwareState::HubHome
|
||||
```
|
||||
|
||||
O firmware MUST NOT apenas retornar ao Hub sem acionar
|
||||
`os.lifecycle().close_task(task_id)`, porque isso deixaria a task/processo
|
||||
dependente de cleanup implicito.
|
||||
|
||||
## Rationale
|
||||
|
||||
O modelo do OS precisa preservar a relacao direta entre task navegavel e janela
|
||||
visual. Se uma Shell task esta em foreground, sua continuidade precisa depender
|
||||
da janela visual da propria task, nao da existencia de qualquer janela focada.
|
||||
|
||||
`focused_window_belongs_to_task(task_id)` e o nome escolhido porque o foco e
|
||||
global no `WindowManager`. A pergunta nao e se a task possui um subsistema de
|
||||
foco proprio, mas se o foco global atual pertence aquela task.
|
||||
|
||||
A consulta pertence a `WindowFacade` porque ela responde sobre janela, foco e
|
||||
ownership. Transicoes de estado continuam pertencendo a `LifecycleFacade`.
|
||||
`ShellRunningStep` coordena os dois dominios no nivel firmware:
|
||||
|
||||
```text
|
||||
WindowFacade
|
||||
responde perguntas sobre janelas, foco e ownership
|
||||
|
||||
LifecycleFacade
|
||||
altera TaskState e ProcessState
|
||||
|
||||
ShellRunningStep
|
||||
coordena a decisao firmware-level entre janela e lifecycle
|
||||
```
|
||||
|
||||
Essa separacao preserva o desenho recente de `SystemOS`: ownership e mediacao
|
||||
continuam centralizados, mas cada facade responde pelo dominio certo.
|
||||
|
||||
## Alternativas Descartadas
|
||||
|
||||
### Manter `focused_window_active`
|
||||
|
||||
Descartado como contrato final porque o booleano generico nao codifica
|
||||
ownership da task. Ele permitiria que uma Shell task continuasse por causa de
|
||||
uma janela pertencente ao `Hub`, a uma `Overlay`, ou a outra task futura.
|
||||
|
||||
### Usar "task possui alguma janela ativa"
|
||||
|
||||
Descartado para v1 porque abre semantica de overlays, multiplas janelas,
|
||||
minimizacao, app switcher e background. Essa direcao pode ser reavaliada em
|
||||
agenda futura, mas e maior que o contrato necessario agora.
|
||||
|
||||
### Lifecycle fecha janelas, mas janelas nunca afetam lifecycle
|
||||
|
||||
Descartado para Shell apps foreground porque permitiria uma Shell task
|
||||
foreground sem presenca visual propria. Isso contradiz o contrato
|
||||
`Window = presenca visual da task` para apps Shell.
|
||||
|
||||
## Invariantes / Contrato
|
||||
|
||||
- `Process` MUST representar execucao tecnica.
|
||||
- `Task` MUST representar presenca navegavel.
|
||||
- `Window` MUST representar presenca visual de Shell/system tasks quando essas
|
||||
tasks sao modeladas pelo `WindowManager`.
|
||||
- Shell app windows MUST usar `WindowOwner::Task(TaskId)`.
|
||||
- `Hub` MUST NOT ser tratado como janela de Shell task.
|
||||
- `Overlay` MUST NOT ser tratado como janela de Shell task nesta v1.
|
||||
- Games MUST NOT ser modelados como `WindowManager` windows.
|
||||
- Games MUST continuar como sessoes fullscreen conduzidas por
|
||||
`GameRunningStep`.
|
||||
- `ShellRunningStep` MUST NOT usar `focused_window_active` como contrato de
|
||||
continuidade da sua task.
|
||||
- `ShellRunningStep` MUST consultar
|
||||
`os.windows().focused_window_belongs_to_task(task_id)` para verificar
|
||||
ownership da janela focada.
|
||||
- Quando a consulta retornar falso para uma Shell task foreground,
|
||||
`ShellRunningStep` MUST chamar `os.lifecycle().close_task(task_id)` e retornar
|
||||
`FirmwareState::HubHome`.
|
||||
- `WindowFacade` MUST responder perguntas de foco, janela e ownership.
|
||||
- `LifecycleFacade` MUST executar mudancas de `TaskState` e `ProcessState`.
|
||||
- Uma futura politica de overlay/modal MUST ser decidida em agenda propria se
|
||||
overlays passarem a roubar foco ou preservar task subjacente.
|
||||
|
||||
## Impactos
|
||||
|
||||
### Spec
|
||||
|
||||
Os specs canonicos MUST documentar o contrato:
|
||||
|
||||
```text
|
||||
Process = execucao tecnica
|
||||
Task = presenca navegavel
|
||||
Window = presenca visual da task
|
||||
```
|
||||
|
||||
Eles tambem MUST documentar que games nao sao janelas, que games rodam via
|
||||
`GameRunningStep`, que Shell apps usam `WindowOwner::Task(TaskId)`, e que v1 de
|
||||
`ShellRunningStep` depende de foco pertencente a propria task.
|
||||
|
||||
### Runtime / System
|
||||
|
||||
`WindowFacade` precisa expor `focused_window_belongs_to_task(task_id)`.
|
||||
`WindowManager` pode continuar sendo o storage de foco e janelas, mas a API
|
||||
publica consumida pelo firmware deve passar pela facade.
|
||||
|
||||
### Firmware
|
||||
|
||||
`ShellRunningStep` deve substituir o uso de `focused_window_active` pela nova
|
||||
consulta em `os.windows()`. Quando o predicado for falso, deve fechar a task via
|
||||
`os.lifecycle().close_task(task_id)` e retornar `HubHome`.
|
||||
|
||||
`GameRunningStep` nao muda por esta decision.
|
||||
|
||||
### Host
|
||||
|
||||
Sem impacto direto esperado. O host nao deve precisar conhecer o contrato
|
||||
Task-Window para Shell task liveness.
|
||||
|
||||
### Firmware / Hub
|
||||
|
||||
O outcome generico `focused_window_active` deixa de ser o contrato de
|
||||
continuidade de `ShellRunningStep`. Ele pode permanecer como detalhe interno ou
|
||||
ser removido em plano posterior, desde que nao seja usado como predicado de
|
||||
liveness da Shell task.
|
||||
|
||||
### Tooling
|
||||
|
||||
Sem impacto direto esperado alem de testes.
|
||||
|
||||
## Propagacao Necessaria
|
||||
|
||||
- Criar plano de execucao a partir desta decision antes de editar specs ou
|
||||
codigo.
|
||||
- Atualizar specs canonicos em ingles com o contrato Task-Window.
|
||||
- Adicionar `focused_window_belongs_to_task(task_id)` em `WindowFacade` e, se
|
||||
fizer sentido para teste unitario, em `WindowManager`.
|
||||
- Alterar `ShellRunningStep` para consultar a nova API e fechar lifecycle antes
|
||||
de retornar `HubHome`.
|
||||
- Ajustar ou remover o uso de `focused_window_active` no caminho de Shell
|
||||
running.
|
||||
- Adicionar testes para:
|
||||
- janela focada da propria task permite continuidade;
|
||||
- janela focada de outro owner fecha a Shell task;
|
||||
- ausencia de foco fecha a Shell task;
|
||||
- fechamento passa por `LifecycleFacade` e para o processo;
|
||||
- games continuam fora do `WindowManager`.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- overlay/modal policy;
|
||||
- background services;
|
||||
- minimizacao;
|
||||
- app switcher;
|
||||
- dock;
|
||||
- multiplas janelas complexas;
|
||||
- redesign da Shell;
|
||||
- transformar games em janelas;
|
||||
- reabrir o contrato geral de `Process`, `Task` e lifecycle.
|
||||
|
||||
## Referencias
|
||||
|
||||
- Agenda: `AGD-0035`
|
||||
- Discussao: `DSC-0035`
|
||||
- Licao relacionada: `LSN-0040` System Pipeline Separation
|
||||
- Licao relacionada: `LSN-0041` SystemOS Lifecycle Authority
|
||||
- Licao relacionada: `LSN-0042` SystemOS Service Ownership Boundary
|
||||
- Licao relacionada: `LSN-0043` SystemOS Domain Facades
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-05-15: Draft inicial criado a partir de `AGD-0035`.
|
||||
@ -1,116 +0,0 @@
|
||||
---
|
||||
id: PLN-0059
|
||||
ticket: task-owned-shell-windows
|
||||
title: Plan - Task Window Contract Specs
|
||||
status: done
|
||||
created: 2026-05-15
|
||||
completed: 2026-05-15
|
||||
ref_decisions: [DEC-0027]
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle, specs]
|
||||
---
|
||||
|
||||
# Plan - Task Window Contract Specs
|
||||
|
||||
## Briefing
|
||||
|
||||
Document the task-owned shell window contract from `DEC-0027` in the canonical
|
||||
runtime specs before code execution changes the observable model.
|
||||
|
||||
## Decisions de Origem
|
||||
|
||||
- `DEC-0027` - Task-Owned Shell Windows
|
||||
|
||||
## Alvo
|
||||
|
||||
The canonical specs must state that:
|
||||
|
||||
- `Process` is technical execution.
|
||||
- `Task` is navigable presence.
|
||||
- `Window` is visual presence for shell/system tasks managed by the
|
||||
`WindowManager`.
|
||||
- Game cartridges are not `WindowManager` windows and continue as fullscreen
|
||||
`GameRunningStep` sessions.
|
||||
- Shell app windows use `WindowOwner::Task(TaskId)`.
|
||||
- `Hub` and `Overlay` are not shell task windows.
|
||||
- v1 `ShellRunningStep` continues only while the focused window belongs to its
|
||||
own task.
|
||||
|
||||
## Escopo
|
||||
|
||||
Included:
|
||||
|
||||
- Update [docs/specs/runtime/12-firmware-pos-and-prometeuhub.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/12-firmware-pos-and-prometeuhub.md) with the contract.
|
||||
- Add or adjust terminology in the same file if the existing terms section is
|
||||
the best local home.
|
||||
- Link the contract to firmware states, AppMode behavior, and Hub/system window
|
||||
responsibilities.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Code changes in `crates/`.
|
||||
- Overlay/modal policy.
|
||||
- Background services, minimization, app switcher, or dock behavior.
|
||||
- Multiple-window semantics beyond preserving future compatibility.
|
||||
- Rewriting unrelated firmware spec sections.
|
||||
|
||||
## Plano de Execucao
|
||||
|
||||
1. Locate the normative spec home.
|
||||
Use `docs/specs/runtime/12-firmware-pos-and-prometeuhub.md` as the primary
|
||||
target because it already owns POS, Hub, AppMode, and firmware states.
|
||||
|
||||
2. Extend the terms section.
|
||||
Add concise definitions for `Process`, `Task`, `Window`, `WindowOwner`, and
|
||||
shell task windows if they are not already present.
|
||||
|
||||
3. Add a Task-Owned Shell Windows section.
|
||||
State the v1 predicate explicitly:
|
||||
|
||||
```text
|
||||
TaskState::Foreground
|
||||
+
|
||||
focused window owner == WindowOwner::Task(task_id)
|
||||
```
|
||||
|
||||
State that the runtime API is
|
||||
`os.windows().focused_window_belongs_to_task(task_id)`.
|
||||
|
||||
4. Clarify AppMode separation.
|
||||
Under `Game`, state that games are fullscreen firmware sessions and must not
|
||||
be modeled as `WindowManager` windows. Under `System`, state that shell apps
|
||||
are represented through task-owned windows.
|
||||
|
||||
5. Clarify lifecycle consequence.
|
||||
State that when a shell task loses its eligible focused window,
|
||||
`ShellRunningStep` must close the task through `SystemOS` lifecycle and then
|
||||
return to Hub.
|
||||
|
||||
6. Keep excluded topics explicit.
|
||||
Add a short note that overlay policy, minimization, app switcher, dock, and
|
||||
background services are future contracts, not part of v1.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- [x] The spec describes the `Process` / `Task` / `Window` model in English.
|
||||
- [x] The spec states that games are not `WindowManager` windows.
|
||||
- [x] The spec states that shell app windows use `WindowOwner::Task(TaskId)`.
|
||||
- [x] The spec states the v1 `ShellRunningStep` focused-window predicate.
|
||||
- [x] The spec states that loss of the eligible focused window closes the task
|
||||
through lifecycle before returning to Hub.
|
||||
- [x] The spec does not introduce overlay, background, minimization, app
|
||||
switcher, dock, or multiple-window policy.
|
||||
|
||||
## Tests / Validacao
|
||||
|
||||
- Run `discussion validate`.
|
||||
- Review the changed spec for English-only normative text.
|
||||
- Confirm every normative point from `DEC-0027` has a corresponding spec line.
|
||||
|
||||
## Riscos
|
||||
|
||||
- The spec may become too implementation-specific if it describes current Rust
|
||||
call sites instead of the contract.
|
||||
- The spec may accidentally imply overlay/modal behavior. Keep overlay
|
||||
behavior explicitly out of scope.
|
||||
- Future work may need a dedicated OS/window spec chapter; this plan keeps the
|
||||
change local to the existing firmware/Hub spec.
|
||||
@ -1,105 +0,0 @@
|
||||
---
|
||||
id: PLN-0060
|
||||
ticket: task-owned-shell-windows
|
||||
title: Plan - Focused Window Ownership API
|
||||
status: done
|
||||
created: 2026-05-15
|
||||
completed: 2026-05-15
|
||||
ref_decisions: [DEC-0027]
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle, code]
|
||||
---
|
||||
|
||||
# Plan - Focused Window Ownership API
|
||||
|
||||
## Briefing
|
||||
|
||||
Add the OS/window query required by `DEC-0027`:
|
||||
`os.windows().focused_window_belongs_to_task(task_id)`.
|
||||
|
||||
This plan owns the system-side API and tests. It does not change firmware
|
||||
control flow; that is covered by `PLN-0061`.
|
||||
|
||||
## Decisions de Origem
|
||||
|
||||
- `DEC-0027` - Task-Owned Shell Windows
|
||||
|
||||
## Alvo
|
||||
|
||||
`WindowFacade` must expose a focused-window ownership predicate that answers
|
||||
whether the global focused window belongs to a specific `TaskId`.
|
||||
|
||||
## Escopo
|
||||
|
||||
Included:
|
||||
|
||||
- Add a focused ownership query to
|
||||
[window.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-system/src/os/facades/window.rs).
|
||||
- Add a helper in
|
||||
[window_manager.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-system/src/services/windows/window_manager.rs) if it keeps the facade thin and testable.
|
||||
- Add unit tests for focused-window ownership in the `prometeu-system` crate.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Changing `ShellRunningStep`.
|
||||
- Removing `focused_window_active` from `PrometeuHubOutcome`.
|
||||
- Spec edits.
|
||||
- Overlay/modal policy or active-window semantics.
|
||||
- Multiple-window policy beyond querying the single global focused window.
|
||||
|
||||
## Plano de Execucao
|
||||
|
||||
1. Add `WindowManager::focused_window_belongs_to_task`.
|
||||
In `crates/console/prometeu-system/src/services/windows/window_manager.rs`,
|
||||
implement a method that:
|
||||
- returns `false` when `focused` is `None`;
|
||||
- finds the focused window by `WindowId`;
|
||||
- returns `true` only when its owner is `WindowOwner::Task(task_id)`;
|
||||
- returns `false` for `Hub`, `Overlay`, another task id, or stale focus.
|
||||
|
||||
2. Add `WindowFacade::focused_window_belongs_to_task`.
|
||||
In `crates/console/prometeu-system/src/os/facades/window.rs`, expose the
|
||||
public facade method and delegate to the manager/helper.
|
||||
|
||||
3. Keep existing facade methods intact.
|
||||
Do not remove `focused_window()` or `windows()` in this plan. Existing call
|
||||
sites may still need them until `PLN-0061` updates firmware.
|
||||
|
||||
4. Add tests in `window_manager.rs`.
|
||||
Cover:
|
||||
- no focused window returns `false`;
|
||||
- focused `WindowOwner::Task(task_id)` returns `true`;
|
||||
- focused `WindowOwner::Task(other_task)` returns `false`;
|
||||
- focused `WindowOwner::Hub` returns `false`;
|
||||
- focused `WindowOwner::Overlay` returns `false`;
|
||||
- stale focused id after window removal returns `false`.
|
||||
|
||||
5. Add facade-level coverage if existing `SystemOS` tests provide a convenient
|
||||
pattern.
|
||||
If facade-level setup would duplicate manager coverage heavily, keep the
|
||||
unit coverage at the manager level and rely on the facade as a direct
|
||||
delegation.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- [x] `os.windows().focused_window_belongs_to_task(task_id)` compiles.
|
||||
- [x] The predicate returns `true` only for the currently focused
|
||||
`WindowOwner::Task(task_id)`.
|
||||
- [x] `Hub`, `Overlay`, absent focus, stale focus, and other task owners return
|
||||
`false`.
|
||||
- [x] No firmware behavior changes are included in this plan.
|
||||
|
||||
## Tests / Validacao
|
||||
|
||||
- Run `cargo test -p prometeu-system`.
|
||||
- Run any narrower test command available for the window manager module if the
|
||||
crate supports it.
|
||||
- Run `discussion validate`.
|
||||
|
||||
## Riscos
|
||||
|
||||
- Directly scanning `windows` by focused id is simple but can hide stale focus
|
||||
bugs. Tests must lock stale focus behavior to `false`.
|
||||
- Adding only a facade method without manager coverage would make the contract
|
||||
harder to verify. Prefer manager tests.
|
||||
- Borrowing through `WindowFacade` must remain short-lived and compatible with
|
||||
existing `SystemOS` facade patterns.
|
||||
@ -1,128 +0,0 @@
|
||||
---
|
||||
id: PLN-0061
|
||||
ticket: task-owned-shell-windows
|
||||
title: Plan - Shell Running Lifecycle Integration
|
||||
status: done
|
||||
created: 2026-05-15
|
||||
completed: 2026-05-15
|
||||
ref_decisions: [DEC-0027]
|
||||
tags: [runtime, os, task, window-manager, shell, lifecycle, firmware, tests]
|
||||
---
|
||||
|
||||
# Plan - Shell Running Lifecycle Integration
|
||||
|
||||
## Briefing
|
||||
|
||||
Integrate the accepted task-owned window contract into `ShellRunningStep`.
|
||||
`ShellRunningStep` must stop using generic focused-window presence as the
|
||||
liveness contract and must close the shell task through lifecycle when the
|
||||
focused window no longer belongs to that task.
|
||||
|
||||
## Decisions de Origem
|
||||
|
||||
- `DEC-0027` - Task-Owned Shell Windows
|
||||
|
||||
## Alvo
|
||||
|
||||
`ShellRunningStep` continues only when:
|
||||
|
||||
```text
|
||||
TaskState::Foreground
|
||||
+
|
||||
os.windows().focused_window_belongs_to_task(task_id)
|
||||
```
|
||||
|
||||
When that predicate is false, the step must call
|
||||
`os.lifecycle().close_task(task_id)` and return `FirmwareState::HubHome`.
|
||||
|
||||
## Escopo
|
||||
|
||||
Included:
|
||||
|
||||
- Update
|
||||
[firmware_step_shell_running.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-firmware/src/firmware/firmware_step_shell_running.rs).
|
||||
- Adjust the shell-running path in
|
||||
[prometeu_hub.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs) only if `focused_window_active` becomes unused or misleading.
|
||||
- Add firmware/system tests proving lifecycle closure and Hub return behavior.
|
||||
- Preserve `GameRunningStep` behavior.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Spec edits; covered by `PLN-0059`.
|
||||
- Adding the window ownership API; covered by `PLN-0060`.
|
||||
- Overlay/modal policy.
|
||||
- Background, minimization, app switcher, dock, or multiple-window behavior.
|
||||
- Treating games as windows.
|
||||
|
||||
## Plano de Execucao
|
||||
|
||||
1. Depend on `PLN-0060`.
|
||||
Do not update `ShellRunningStep` until
|
||||
`os.windows().focused_window_belongs_to_task(task_id)` exists.
|
||||
|
||||
2. Replace the liveness predicate in `ShellRunningStep`.
|
||||
In `firmware_step_shell_running.rs`, keep the existing `TaskState`
|
||||
validation. After `ctx.hub.update_shell_profile(...)`, replace the
|
||||
`outcome.focused_window_active` check with:
|
||||
|
||||
```text
|
||||
!ctx.os.windows().focused_window_belongs_to_task(self.task_id)
|
||||
```
|
||||
|
||||
3. Preserve crash handling order.
|
||||
Keep VM crash handling before window-liveness closure so a crash reported by
|
||||
the shell update remains a crash, not a normal close.
|
||||
|
||||
4. Close through lifecycle before returning Hub.
|
||||
When the focused-window ownership predicate is false:
|
||||
- log the closure with task id;
|
||||
- call `ctx.os.lifecycle().close_task(self.task_id)`;
|
||||
- log lifecycle close errors;
|
||||
- return `Some(FirmwareState::HubHome(HubHomeStep))`.
|
||||
|
||||
5. De-emphasize or remove `focused_window_active`.
|
||||
If `SystemProfileUpdate.focused_window_active` has no remaining call sites,
|
||||
remove it from `SystemProfileUpdate` and its construction. If another
|
||||
legitimate caller remains, keep it but do not use it for shell task
|
||||
liveness.
|
||||
|
||||
6. Add or update tests.
|
||||
Use existing firmware tests in
|
||||
[firmware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-firmware/src/firmware/firmware.rs)
|
||||
or a nearby test module. Cover:
|
||||
- focused task-owned window keeps the shell path running;
|
||||
- no focused window closes task and returns `HubHome`;
|
||||
- focused `Hub` window closes task and returns `HubHome`;
|
||||
- focused `Overlay` window closes task and returns `HubHome` in v1;
|
||||
- focused window for another task closes task and returns `HubHome`;
|
||||
- lifecycle close changes task to `Closed` and process to `Stopped`;
|
||||
- `GameRunningStep` remains independent from `WindowManager`.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- [x] `ShellRunningStep` no longer uses `focused_window_active` as its
|
||||
continuation contract.
|
||||
- [x] `ShellRunningStep` uses
|
||||
`os.windows().focused_window_belongs_to_task(self.task_id)`.
|
||||
- [x] A false predicate closes the task through lifecycle before returning
|
||||
`HubHome`.
|
||||
- [x] `Hub`, `Overlay`, absent focus, and another task's focused window all
|
||||
fail the predicate for the current shell task.
|
||||
- [x] Game-running behavior is unchanged and remains outside `WindowManager`.
|
||||
|
||||
## Tests / Validacao
|
||||
|
||||
- Run `cargo test -p prometeu-system`.
|
||||
- Run `cargo test -p prometeu-firmware`.
|
||||
- Run a workspace or targeted build command used by this repository if the two
|
||||
crate tests are not sufficient.
|
||||
- Run `discussion validate`.
|
||||
|
||||
## Riscos
|
||||
|
||||
- Current Hub update behavior may close or replace windows during the same tick;
|
||||
tests need to account for the final focused window after `update_shell_profile`.
|
||||
- Removing `focused_window_active` may require small cleanup in system tests or
|
||||
callers.
|
||||
- The v1 overlay behavior is intentionally strict. Do not add overlay
|
||||
preservation logic in this plan.
|
||||
Loading…
x
Reference in New Issue
Block a user