diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 45e474a3..419f40a8 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ -{"type":"meta","next_id":{"DSC":35,"AGD":35,"DEC":27,"PLN":59,"LSN":43,"CLSN":1}} -{"type":"discussion","id":"DSC-0034","status":"in_progress","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":[{"id":"AGD-0034","file":"AGD-0034-agenda-systemos-domain-facades.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15"}],"decisions":[{"id":"DEC-0026","file":"DEC-0026-systemos-domain-facades.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0058","file":"PLN-0058-systemos-domain-facades-first-wave.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0026"]}],"lessons":[]} +{"type":"meta","next_id":{"DSC":35,"AGD":35,"DEC":27,"PLN":59,"LSN":44,"CLSN":1}} +{"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"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} diff --git a/discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md b/discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md new file mode 100644 index 00000000..ddedbbb8 --- /dev/null +++ b/discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md @@ -0,0 +1,95 @@ +--- +id: LSN-0043 +ticket: system-os-domain-facades +title: SystemOS Domain Facades +created: 2026-05-15 +tags: [runtime, os, services, api-surface, lifecycle, fs] +--- + +## Context + +`SystemOS` became the owner and mediator for core OS services: VM runtime, +lifecycle, filesystem, memcard, window management, task/process state and +logging. That ownership boundary is correct, but exposing every service field +and operation on the root made the OS surface too broad. + +The solution was not to split ownership back out of `SystemOS`; it was to split +the public access surface into short-lived domain views. + +## Key Decisions + +### Use method-based domain facades + +**What:** `SystemOS` exposes domain entry points such as: + +```rust +os.lifecycle() +os.sessions() +os.vm() +os.fs() +os.window() +``` + +Each accessor returns a borrow-friendly facade over `SystemOS` internals. + +**Why:** Direct fields such as `os.lifecycle.suspend_task(...)` look attractive, +but they force ownership shape too early. Method-based views preserve Rust +borrowing flexibility while still making the domain boundary explicit. + +**Trade-offs:** Callers write `os.lifecycle().suspend_task(...)` instead of +`os.lifecycle.suspend_task(...)`. The extra call is worth the cleaner ownership +model. + +### Keep logging on the root + +**What:** `os.log(...)` remains root-level. + +**Why:** Logging is cross-cutting, short and used by multiple domains. It is not +a broad policy surface in the same way lifecycle, VM, fs or window management +are. + +**Trade-offs:** The root is not empty, but it remains intentionally small. + +### Hide migrated internals + +**What:** Direct access to internal fields such as task/process managers, window +manager and VM runtime should disappear once the corresponding facade exists. + +**Why:** Public internals let callers bypass OS policy. Facades force callers to +use the semantic boundary instead of stitching together lower-level services. + +**Trade-offs:** Tests need domain-level inspection helpers instead of reaching +into raw fields. That is better than keeping production internals public for +test convenience. + +## Patterns and Algorithms + +Use a short-lived view when an operation needs access to several `SystemOS` +fields: + +```rust +os.lifecycle().crash_task(task_id, Some(&report)); +os.vm().tick(vm, signals, hw); +os.window().set_focus(window_id); +``` + +The facade should borrow `SystemOS` or the necessary internals; it must not own +duplicated state. If a domain later becomes a true independently owned service, +that should be a separate decision. + +## Pitfalls + +- Do not solve a wide root by moving ownership out of `SystemOS` prematurely. +- Do not keep raw managers public just because tests need inspection. +- Do not make facades long-lived when short-lived method calls avoid borrow + pressure. +- Do not invent new filesystem behavior while creating an `fs()` facade; expose + existing behavior first. + +## Takeaways + +- Ownership boundary and public API shape are separate architectural questions. +- `SystemOS` can remain the owner while exposing a narrower domain-oriented API. +- Method-based facades are a pragmatic Rust shape for OS domains that coordinate + multiple internal services. +- A small root API makes OS policy harder to bypass and easier to document. diff --git a/discussion/workflow/agendas/AGD-0034-agenda-systemos-domain-facades.md b/discussion/workflow/agendas/AGD-0034-agenda-systemos-domain-facades.md deleted file mode 100644 index 2e0e240a..00000000 --- a/discussion/workflow/agendas/AGD-0034-agenda-systemos-domain-facades.md +++ /dev/null @@ -1,353 +0,0 @@ ---- -id: AGD-0034 -ticket: system-os-domain-facades -title: Agenda - SystemOS Domain Facades -status: accepted -created: 2026-05-15 -resolved: 2026-05-15 -decision: DEC-0026 -tags: [runtime, os, services, api-surface, lifecycle, fs] ---- - -# Agenda - SystemOS Domain Facades - -## Contexto - -Depois de `DEC-0024` e `DEC-0025`, `SystemOS` passou a concentrar ownership e -coordenação de vários domínios do Prometeu OS: - -```text -SystemOS - vm_runtime - process_manager - task_manager - window_manager - log_service - fs / fs_state / open_files / next_handle - memcard - lifecycle methods - VM initialize/tick helpers -``` - -Essa concentração é correta do ponto de vista de ownership: o OS deve ser dono -ou mediador dos serviços do console. O problema agora é a superfície pública do -root. Se tudo fica como `os.bla()`, `os.campo.bla()` ou campos públicos soltos, -o `SystemOS` vira um objeto largo demais e deixa de comunicar domínio. - -A intenção proposta é separar a superfície em compartimentos: - -```text -os.lifecycle().suspend_task(...) -os.lifecycle().resume_task(...) -os.lifecycle().crash_task(...) - -os.sessions().create_vm_game_task(...) -os.sessions().create_vm_shell_task(...) -os.sessions().create_native_shell_task(...) - -os.vm().initialize(...) -os.vm().tick(...) - -os.fs().mount(...) -os.fs().open(...) -os.fs().read(...) -os.fs().write(...) -os.fs().close(...) - -os.window().add_window(...) -os.window().set_focus(...) -os.window().focused_window(...) -os.window().close_window(...) -``` - -Logging pode continuar na raiz como operação transversal: - -```text -os.log(...) -``` - -## Problema - -O `SystemOS` está crescendo wild na raiz. Isso cria alguns riscos: - -- novos domínios tendem a adicionar mais métodos diretamente em `SystemOS`; -- lifecycle, filesystem, window, VM runtime e memcard competem pela mesma - superfície; -- testes e firmware continuam alcançando managers internos diretamente; -- fica difícil distinguir API semântica de OS de detalhe interno de serviço; -- a raiz pública pode virar uma coleção de campos públicos em vez de uma - interface de sistema. - -O ponto importante: não queremos desfazer o ownership do `SystemOS`. Queremos -compartimentalizar o acesso. - -## Pontos Criticos - -- `SystemOS` deve continuar sendo o boundary de ownership e coordenação. -- Facades não devem virar owners independentes que duplicam estado. -- A raiz do OS deve ficar pequena e expressiva. -- Lifecycle deve continuar coordenando `TaskState` e `ProcessState` junto. -- Filesystem tem estado composto (`VirtualFS`, `FsState`, `open_files`, - `next_handle`) e por isso se beneficia de uma facade própria. -- Window management já é serviço do OS, mas `PrometeuHub` e firmware ainda - acessam `os.window_manager` diretamente. -- VM runtime talvez também precise de facade ou área própria, mas isso pode ser - uma etapa posterior para não misturar com lifecycle/fs. -- O formato da facade precisa respeitar borrow rules em Rust; campos públicos - simples podem não ser viáveis quando uma operação precisa de múltiplos campos - internos do `SystemOS`. - -## Opcoes - -### Opcao A - Manter tudo na raiz do SystemOS - -**Abordagem:** -Continuar adicionando métodos e campos diretamente em `SystemOS`. - -**Vantagens:** -- menor mudança imediata; -- callsites simples; -- menos tipos auxiliares; -- evita atrito com borrow checker. - -**Custos / Riscos:** -- a raiz continua crescendo; -- domínios ficam misturados; -- incentiva acesso direto a managers internos; -- torna mais difícil explicar a API do OS; -- cada nova capability aumenta a pressão no mesmo arquivo e no mesmo objeto. - -**Manutenibilidade:** -Fraca no médio prazo. - -### Opcao B - Criar facades de domínio em torno do SystemOS - -**Abordagem:** -Criar facades estreitas por domínio, expostas como acesso semântico: - -```text -os.lifecycle().suspend_task(...) -os.fs().mount(...) -os.window().set_focus(...) -``` - -Ou, se o design permitir sem duplicar ownership: - -```text -os.lifecycle.suspend_task(...) -os.fs.mount(...) -os.window.set_focus(...) -``` - -As facades seriam views/handles sobre os campos internos do `SystemOS`, não -owners independentes. - -**Vantagens:** -- deixa a raiz do OS menor; -- agrupa API por domínio; -- torna mais claro o que é lifecycle, fs, window, memcard e VM; -- ajuda a esconder managers internos; -- reduz a chance de firmware coordenar detalhes por fora. - -**Custos / Riscos:** -- exige decidir padrão de borrowing; -- pode adicionar tipos pequenos e boilerplate; -- `os.lifecycle.bla()` como campo direto pode ser difícil se a facade precisar - acessar `task_manager` e `process_manager` que vivem no mesmo `SystemOS`; -- talvez precise começar com métodos `os.lifecycle()` em vez de campos públicos. - -**Manutenibilidade:** -Forte se as facades forem views estreitas e não novos owners. - -### Opcao C - Criar services owners independentes dentro do SystemOS - -**Abordagem:** -Mover estado e lógica para structs owned diretamente: - -```text -SystemOS - lifecycle: LifecycleService - fs: FileSystemService - window: WindowService -``` - -Cada service seria owner do seu próprio estado ou de parte dele. - -**Vantagens:** -- aproxima o shape desejado `os.lifecycle.bla()`; -- reduz métodos no root; -- pode simplificar alguns domínios autocontidos. - -**Custos / Riscos:** -- lifecycle precisa coordenar task/process, então ownership separado pode criar - borrow/coordenação mais difícil; -- filesystem hoje cruza VM syscall state, `VirtualFS`, `FsState`, handles e - logging; -- pode reabrir decisões de ownership que acabaram de estabilizar; -- risco de mover estado cedo demais para caber numa estética de API. - -**Manutenibilidade:** -Boa para domínios autocontidos, arriscada para lifecycle neste momento. - -## Sugestao / Recomendacao - -A direção recomendada é **Opção B: facades de domínio como views estreitas sobre -o `SystemOS`**. - -O corte recomendado é: - -```text -SystemOS - lifecycle() - set_foreground_task - suspend_task - resume_task - close_task - crash_task - - sessions() - create_vm_game_task - create_vm_shell_task - create_native_shell_task - - vm() - initialize - tick - - fs() - mount - open - read - write - close - - window() - add_window - set_focus - focused_window - close_window - - log(...) -``` - -E evitar que a raiz acumule: - -```text -suspend_task -resume_task -close_task -crash_task -mount_fs -initialize_vm -tick_vm -create_vm_game_task -create_vm_shell_task -create_native_shell_task -window_manager direto -task_manager direto -process_manager direto -vm_runtime direto -fs direto -memcard direto -``` - -Para Rust, o primeiro corte provavelmente deve usar métodos de acesso que -retornam views: - -```rust -os.lifecycle().suspend_task(task_id) -os.fs().mount(backend) -os.window().set_focus(window_id) -``` - -Isso é menos bonito que campo direto, mas evita congelar ownership errado. Se -mais tarde algum domínio puder virar service owner real, podemos migrar para -campo direto sem mudar a semântica. - -Logging pode permanecer na raiz: - -```rust -os.log(...) -``` - -Motivo: logging é transversal, curto, usado por várias etapas do firmware, e não -carrega sozinho uma política complexa de estado. - -## Perguntas em Aberto - -- [x] Queremos a sintaxe ideal `os.lifecycle.bla()` mesmo que isso force - services owners reais, ou aceitamos `os.lifecycle().bla()` como primeira forma - borrow-friendly? quando escrevi os.lifecycle.bla() eu queria mesmo era os.lifecycle().bla() -- [x] Quais domínios entram no primeiro corte: só `lifecycle` e `fs`, ou também - `window`? nao precisamos criar nada, mas lifecycle, fs, window e vm sao easy wins no meu ponto de vista -- [x] `create_vm_game_task` e `create_vm_shell_task` pertencem a - `os.lifecycle()`, a `os.processes()/os.tasks()`, ou a um futuro domínio - `os.apps()/os.sessions()`? vamos de os.session() para esses. -- [x] `tick_vm` e `initialize_vm` devem ficar temporariamente na raiz, ou já - entrar em `os.vm()`? isso, os.vm(). -- [x] Campos como `task_manager`, `process_manager`, `window_manager`, - `vm_runtime`, `fs`, `memcard` devem deixar de ser públicos no mesmo corte ou - em planos graduais? eu nao os deixaria publicos desde jah, isso forca a politica de facades dentro de system os. -- [x] Como preservar testes sem criar APIs públicas só para inspeção? Testes devem ser feitos nos subdomínios; SystemOS só testa composição e coordenação que não pertence isoladamente a um domínio. - -## Resolucao Proposta - -A agenda deve fechar pela **Opção B**. - -O `SystemOS` continua sendo o owner e boundary de coordenação, mas sua superfície -pública deve ser compartimentalizada em facades de domínio. A forma normativa -inicial deve ser por métodos que retornam views borrow-friendly: - -```rust -os.lifecycle().suspend_task(task_id) -os.sessions().create_vm_game_task(app_id, title) -os.vm().initialize(vm, cartridge) -os.fs().mount(backend) -os.window().set_focus(window_id) -os.log(level, source, tag, msg) -``` - -A sintaxe com campo direto (`os.lifecycle.suspend_task(...)`) não é requisito -deste corte. A intenção semântica é domínio explícito; a forma prática inicial -deve respeitar ownership e borrowing em Rust. - -Domínios do primeiro corte: - -- `lifecycle()`: lifecycle semântico de task/process. -- `sessions()`: criação de tasks/processos de jogo e shell. -- `vm()`: inicialização e tick da VM. -- `fs()`: filesystem operacional. -- `window()`: operações mínimas de janela/foco. -- `log(...)`: permanece na raiz como operação transversal. - -Campos internos como `task_manager`, `process_manager`, `window_manager`, -`vm_runtime`, `fs`, `fs_state`, `memcard`, `open_files` e `next_handle` devem -deixar de ser públicos já neste corte, salvo se um plan específico demonstrar -necessidade temporária de migração. A política desejada é forçar acesso por -facades dentro do `SystemOS`. - -Testes devem migrar para os subdomínios quando estiverem validando comportamento -de domínio. `SystemOS` deve testar apenas composição e coordenação que realmente -não pertence isoladamente a um domínio. - -## Criterio para Encerrar - -Esta agenda pode virar decisão quando fecharmos: - -- qual forma de facade será normativa: campo direto, método view, ou service - owner; **resolvido: método view borrow-friendly.** -- quais domínios entram no primeiro corte; - **resolvido: lifecycle, sessions, vm, fs, window e log na raiz.** -- quais APIs permanecem no root; - **resolvido: `new`/construção e `log(...)`; demais APIs devem migrar para - facades.** -- se campos internos deixam de ser públicos agora ou em ondas; - **resolvido: deixar de ser públicos já no corte, com exceção transitória - somente se plan demonstrar necessidade.** -- como lifecycle, fs e window serão acessados por firmware, Hub e testes. - **resolvido: por facades; testes de domínio nos subdomínios.** - -## Proximo Passo - -Esta agenda está pronta para decisão normativa se a resolução proposta for -aceita. diff --git a/discussion/workflow/decisions/DEC-0026-systemos-domain-facades.md b/discussion/workflow/decisions/DEC-0026-systemos-domain-facades.md deleted file mode 100644 index f6bf6cc3..00000000 --- a/discussion/workflow/decisions/DEC-0026-systemos-domain-facades.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -id: DEC-0026 -ticket: system-os-domain-facades -title: SystemOS Domain Facades -status: accepted -created: 2026-05-15 -ref_agenda: AGD-0034 -tags: [runtime, os, services, api-surface, lifecycle, fs] ---- - -## Status - -Accepted. Esta decisão foi aceita em 2026-05-15 e passa a ser referência -normativa para compartimentalizar a superfície pública do `SystemOS`. - -## Contexto - -`DEC-0024` consolidou `SystemOS` como owner de serviços do Prometeu OS. -`DEC-0025` colocou o lifecycle de `Task` e `Process` sob autoridade do -`SystemOS`. - -Essas decisões estão corretas em termos de ownership, mas fizeram a raiz do -`SystemOS` crescer como superfície pública. Hoje a raiz mistura runtime VM, -filesystem, memcard, window management, lifecycle, managers internos, handles -operacionais e helpers de criação de tasks/processos. - -Esta decisão não muda o ownership: `SystemOS` continua sendo o boundary do OS. -O que muda é a forma normativa de acesso aos domínios. - -## Decisao - -`SystemOS` SHALL expose OS behavior through domain facades. - -The canonical first-wave access shape SHALL be method-based, borrow-friendly -views: - -```rust -os.lifecycle().suspend_task(task_id) -os.sessions().create_vm_game_task(app_id, title) -os.vm().initialize(vm, cartridge) -os.fs().mount(backend) -os.window().set_focus(window_id) -os.log(level, source, tag, msg) -``` - -Direct field syntax such as `os.lifecycle.suspend_task(...)` is NOT required in -this wave. Domain clarity is normative; direct field ownership is not. - -The first-wave `SystemOS` root SHALL keep only minimal root operations: - -```text -SystemOS - new(...) - log(...) - lifecycle() - sessions() - vm() - fs() - window() -``` - -`log(...)` MAY remain on the root because logging is a cross-cutting operation -used by multiple firmware and OS domains. - -The first-wave domain surface SHALL be: - -```text -lifecycle() - set_foreground_task - suspend_task - resume_task - close_task - crash_task - -sessions() - create_vm_game_task - create_vm_shell_task - create_native_shell_task - -vm() - initialize - tick - -fs() - mount - open - read - write - close - -window() - add_window - set_focus - focused_window - close_window -``` - -Internal service state SHALL NOT remain public on `SystemOS` once the -corresponding facade exists. This includes: - -- `task_manager` -- `process_manager` -- `window_manager` -- `vm_runtime` -- `fs` -- `fs_state` -- `memcard` -- `open_files` -- `next_handle` - -Plans MAY use temporary transitional access only when needed to keep migrations -small, but the completed first-wave facade migration MUST remove direct public -access for migrated domains. - -## Rationale - -`SystemOS` should remain the owner of OS services, but callers should not see it -as a bag of unrelated fields and root methods. Domain facades make the API read -like an OS surface: - -- lifecycle operations live under lifecycle; -- session construction lives under sessions; -- VM execution lives under vm; -- filesystem operations live under fs; -- window operations live under window; -- logging remains root-level because it cuts across domains. - -Method-based facades are preferred over direct fields in this wave because they -preserve Rust borrowing flexibility. A facade can be a temporary view over -multiple internal fields without forcing premature service ownership splits. - -This also protects `DEC-0025`: lifecycle remains the semantic coordinator for -`TaskState` and `ProcessState`, but callers reach it through -`os.lifecycle()`, not through root methods or direct manager access. - -## Invariantes / Contrato - -- `SystemOS` MUST remain the OS ownership and coordination boundary. -- Facades MUST be views or handles over `SystemOS` internals unless a later - decision explicitly promotes a domain to an independently owned service. -- Facades MUST NOT duplicate state. -- Root-level `SystemOS` API MUST stay minimal. -- Lifecycle operations MUST move from root-level `SystemOS` methods to - `os.lifecycle()`. -- Session creation helpers MUST move to `os.sessions()`. -- VM initialization and ticking MUST move to `os.vm()`. -- Filesystem operations MUST move to `os.fs()`. -- Window operations MUST move to `os.window()`. -- Logging MAY remain as `os.log(...)`. -- Firmware, Hub and tests SHOULD use facades instead of direct internal fields. -- Tests for domain behavior SHOULD live at the facade/domain level. -- `SystemOS` tests SHOULD focus on composition and cross-domain coordination. - -## Impactos - -- `crates/console/prometeu-system/src/os/` should gain facade/view types for - lifecycle, sessions, VM, filesystem and window domains. -- Existing root methods such as `suspend_task`, `resume_task`, `close_task`, - `crash_task`, `initialize_vm`, `tick_vm`, `mount_fs`, `create_vm_game_task`, - `create_vm_shell_task` and `create_native_shell_task` should migrate behind - domain facades. -- Direct access to managers and service fields from firmware, Hub and tests - should be removed or narrowed. -- Filesystem state may require a dedicated facade because it spans `VirtualFS`, - `FsState`, file handles, memcard-adjacent state and logging. -- Window access should move away from `os.window_manager` to `os.window()`. -- Specs do not need immediate updates unless these facades become part of a - published external API. - -## Referencias - -- Agenda: `AGD-0034` -- Related decision: `DEC-0024` -- Related decision: `DEC-0025` - -## Propagacao Necessaria - -- Plans: create small plans for lifecycle facade, sessions/vm facade, fs facade, - window facade and internal field encapsulation. -- Code: update `prometeu-system`, firmware, Hub and tests to use domain - facades. -- Tests: move lifecycle/session/fs/window assertions to domain-level tests where - possible. -- Discussion: keep this decision separate from future decisions about true - service ownership splits. - -## Revisao - -- 2026-05-15: Initial accepted decision from `AGD-0034`. diff --git a/discussion/workflow/plans/PLN-0058-systemos-domain-facades-first-wave.md b/discussion/workflow/plans/PLN-0058-systemos-domain-facades-first-wave.md deleted file mode 100644 index 0ac1a228..00000000 --- a/discussion/workflow/plans/PLN-0058-systemos-domain-facades-first-wave.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -id: PLN-0058 -ticket: system-os-domain-facades -title: SystemOS Domain Facades First Wave -status: open -created: 2026-05-15 -ref_decisions: [DEC-0026] -tags: [runtime, os, services, api-surface, lifecycle, fs] ---- - -## Briefing - -Implement the first wave of `SystemOS` domain facades required by `DEC-0026`. -`SystemOS` remains the OS ownership boundary, but callers must access behavior -through domain views instead of root-level methods or public internal fields. - -## Source Decisions - -- `DEC-0026`: `SystemOS` must expose method-based domain facades for lifecycle, - sessions, VM, filesystem and window operations, while keeping `log(...)` on - the root. -- Related: `DEC-0025` keeps lifecycle coordination under `SystemOS`. -- Related: `DEC-0024` keeps services owned or mediated by `SystemOS`. - -## Target - -Create these first-wave access shapes: - -```rust -os.lifecycle().suspend_task(task_id) -os.sessions().create_vm_game_task(app_id, title) -os.vm().initialize(vm, cartridge) -os.vm().tick(vm, signals, hw) -os.fs().mount(backend) -os.window().set_focus(window_id) -os.log(level, source, tag, msg) -``` - -After this plan, migrated domains must no longer require public direct access -to `task_manager`, `process_manager`, `window_manager`, `vm_runtime`, `fs`, -`fs_state`, `memcard`, `open_files` or `next_handle`. - -## Scope - -- Add facade/view types under `crates/console/prometeu-system/src/os/`. -- Add `SystemOS` methods: - - `lifecycle()` - - `sessions()` - - `vm()` - - `fs()` - - `window()` -- Move root lifecycle methods behind `lifecycle()`. -- Move task/process session creation behind `sessions()`. -- Move VM initialization/ticking/reset or execution helpers behind `vm()`. -- Move filesystem mount/open/read/write/close entry points behind `fs()` when - the operation exists at OS level. -- Move window operations behind `window()`. -- Keep `SystemOS::log(...)` at root. -- Migrate firmware, Hub and tests to facade access. -- Make migrated internal `SystemOS` fields private. - -## Out of Scope - -- Changing service ownership established by `DEC-0024`. -- Changing lifecycle semantics established by `DEC-0025`. -- Introducing `os.lifecycle` as a direct public field. -- Background lifecycle semantics. -- New filesystem syscall behavior beyond exposing existing OS-owned operations. -- Diagnostics/crash report persistence. -- Redesigning Hub UI or app switching. -- Replacing VM runtime tests that intentionally test `VirtualMachineRuntime` - directly. - -## Execution Plan - -1. Create facade modules and view types. - - Target files: - - `crates/console/prometeu-system/src/os/mod.rs` - - `crates/console/prometeu-system/src/os/system_os.rs` - - new facade modules under `crates/console/prometeu-system/src/os/` - - Define mutable view structs such as `LifecycleFacade<'a>`, - `SessionsFacade<'a>`, `VmFacade<'a>`, `FsFacade<'a>` and - `WindowFacade<'a>`. - - Each facade should borrow the needed `SystemOS` internals and must not own - duplicated state. - -2. Add `SystemOS` facade accessors. - - Add `SystemOS::lifecycle(&mut self) -> LifecycleFacade<'_>`. - - Add `SystemOS::sessions(&mut self) -> SessionsFacade<'_>`. - - Add `SystemOS::vm(&mut self) -> VmFacade<'_>`. - - Add `SystemOS::fs(&mut self) -> FsFacade<'_>`. - - Add `SystemOS::window(&mut self) -> WindowFacade<'_>`. - - Keep `SystemOS::new(...)` and `SystemOS::log(...)` on the root. - -3. Move lifecycle operations. - - Target existing logic in `crates/console/prometeu-system/src/os/system_os.rs`. - - Move or delegate: - - `set_foreground_task` - - `suspend_task` - - `resume_task` - - `close_task` - - `crash_task` - - The facade must preserve typed `LifecycleError` behavior. - - Callers should use `os.lifecycle().crash_task(...)` rather than - `os.crash_task(...)`. - -4. Move session creation operations. - - Move or delegate: - - `create_vm_game_task` - - `create_vm_shell_task` - - `create_native_shell_task` - - These operations may call the lifecycle facade internally to foreground - newly created tasks. - - Firmware should use `ctx.os.sessions().create_vm_game_task(...)` and - `ctx.os.sessions().create_vm_shell_task(...)`. - -5. Move VM operations. - - Move or delegate: - - `initialize_vm` as `os.vm().initialize(...)` - - `tick_vm` as `os.vm().tick(...)` - - Include reset access if needed to remove direct `os.vm_runtime.reset(...)` - from firmware. - - Preserve VM runtime behavior and logging. - -6. Move filesystem operations. - - Move or delegate existing root filesystem operations: - - `mount_fs` as `os.fs().mount(...)` - - `unmount_fs` if still present, even though `DEC-0026` only names - mount/open/read/write/close for the target surface. - - Expose OS-owned open/read/write/close only if those operations already have - a suitable service-level implementation; otherwise leave them as explicit - follow-up within the facade module without inventing new behavior. - - Keep filesystem state private to `SystemOS`/facade internals. - -7. Move window operations. - - Target: - - `crates/console/prometeu-system/src/services/window_manager.rs` - - `crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs` - - firmware launch tests and cartridge loading. - - Provide facade operations: - - `add_window` - - `set_focus` - - `focused_window` - - `close_window` - - Add any narrow helper needed to preserve existing behavior such as removing - all windows, but keep it under `window()` rather than exposing - `window_manager`. - -8. Encapsulate migrated fields. - - In `SystemOS`, remove `pub` from migrated internals once callsites have - moved: - - `vm_runtime` - - `process_manager` - - `task_manager` - - `window_manager` - - `fs` - - `fs_state` - - `memcard` - - `open_files` - - `next_handle` - - Keep `log_service` private unless a plan proves a public log handle is - required. - - Avoid adding compatibility root methods for the old surface. - -9. Update tests. - - Move `SystemOS` lifecycle tests to facade calls. - - Update firmware tests to observe state through facades or domain-specific - inspection helpers rather than direct internal fields. - - Preserve direct `VirtualMachineRuntime` tests where they test the VM runtime - service itself, not `SystemOS`. - -## Acceptance Criteria - -- `SystemOS` exposes `lifecycle()`, `sessions()`, `vm()`, `fs()` and `window()`. -- Root `SystemOS` keeps `new(...)` and `log(...)`. -- Lifecycle callsites use `os.lifecycle()`. -- Session creation callsites use `os.sessions()`. -- VM initialization/tick/reset callsites use `os.vm()`. -- Window callsites use `os.window()`. -- Existing root methods migrated by this plan are removed or made private. -- Migrated internal fields no longer remain public on `SystemOS`. -- No facade duplicates service state. -- Existing behavior remains unchanged. - -## Tests / Validation - -- Run `cargo test -p prometeu-system`. -- Run `cargo test -p prometeu-firmware`. -- Run `discussion validate`. -- Confirm with search that migrated callsites no longer use: - - `os.task_manager` - - `os.process_manager` - - `os.window_manager` - - `os.vm_runtime` - - `os.suspend_task` - - `os.resume_task` - - `os.close_task` - - `os.crash_task` - - `os.initialize_vm` - - `os.tick_vm` - - `os.create_vm_game_task` - - `os.create_vm_shell_task` - -## Risks - -- Borrowing may require facades to expose narrow methods rather than returning - long-lived mutable references. Keep facades short-lived and method-based. -- Some tests currently inspect internal fields directly. Prefer domain-level - inspection helpers over keeping fields public. -- Filesystem `open/read/write/close` may not all exist as OS-level operations - yet. Do not invent new filesystem semantics while implementing the facade. -- Removing all public internals in one change can be broad. If a field cannot be - hidden without unrelated redesign, document the temporary exception in the - implementation and leave a follow-up plan. - -## Affected Artifacts - -- `crates/console/prometeu-system/src/os/**` -- `crates/console/prometeu-system/src/programs/prometeu_hub/**` -- `crates/console/prometeu-system/src/services/window_manager.rs` -- `crates/console/prometeu-firmware/src/firmware/**` -- `discussion/index.ndjson` -- `discussion/workflow/plans/PLN-0058-systemos-domain-facades-first-wave.md`