housekeeping
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/head This commit looks good
Intrepid/Prometeu/Runtime/pipeline/pr-master This commit looks good

This commit is contained in:
bQUARKz 2026-05-15 15:51:41 +01:00
parent c2698e6a22
commit 82a3380426
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
7 changed files with 114 additions and 1021 deletions

View File

@ -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"}]}

View File

@ -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.

View File

@ -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`.

View File

@ -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`.

View File

@ -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.

View File

@ -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.

View File

@ -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.