diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 93123ad9..ba91153e 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -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"}]} diff --git a/discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md b/discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md new file mode 100644 index 00000000..c6dadf5d --- /dev/null +++ b/discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md @@ -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. diff --git a/discussion/workflow/agendas/AGD-0035-agenda-task-owned-shell-windows.md b/discussion/workflow/agendas/AGD-0035-agenda-task-owned-shell-windows.md deleted file mode 100644 index cd3ee222..00000000 --- a/discussion/workflow/agendas/AGD-0035-agenda-task-owned-shell-windows.md +++ /dev/null @@ -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`. diff --git a/discussion/workflow/decisions/DEC-0027-decision-task-owned-shell-windows.md b/discussion/workflow/decisions/DEC-0027-decision-task-owned-shell-windows.md deleted file mode 100644 index ae507865..00000000 --- a/discussion/workflow/decisions/DEC-0027-decision-task-owned-shell-windows.md +++ /dev/null @@ -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`. diff --git a/discussion/workflow/plans/PLN-0059-plan-task-window-contract-specs.md b/discussion/workflow/plans/PLN-0059-plan-task-window-contract-specs.md deleted file mode 100644 index 0a247675..00000000 --- a/discussion/workflow/plans/PLN-0059-plan-task-window-contract-specs.md +++ /dev/null @@ -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. diff --git a/discussion/workflow/plans/PLN-0060-plan-focused-window-ownership-api.md b/discussion/workflow/plans/PLN-0060-plan-focused-window-ownership-api.md deleted file mode 100644 index 0f624c43..00000000 --- a/discussion/workflow/plans/PLN-0060-plan-focused-window-ownership-api.md +++ /dev/null @@ -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. diff --git a/discussion/workflow/plans/PLN-0061-plan-shell-running-lifecycle-integration.md b/discussion/workflow/plans/PLN-0061-plan-shell-running-lifecycle-integration.md deleted file mode 100644 index 413468cf..00000000 --- a/discussion/workflow/plans/PLN-0061-plan-shell-running-lifecycle-integration.md +++ /dev/null @@ -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.