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

This commit is contained in:
bQUARKz 2026-05-15 10:46:58 +01:00
parent 15615f3b54
commit 1663ab5413
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
5 changed files with 97 additions and 767 deletions

View File

@ -1,5 +1,5 @@
{"type":"meta","next_id":{"DSC":35,"AGD":35,"DEC":27,"PLN":59,"LSN":43,"CLSN":1}} {"type":"meta","next_id":{"DSC":35,"AGD":35,"DEC":27,"PLN":59,"LSN":44,"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":"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-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-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"}]} {"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"}]}

View File

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

View File

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

View File

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

View File

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