11 KiB
| id | ticket | title | status | created | resolved | decision | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AGD-0034 | system-os-domain-facades | Agenda - SystemOS Domain Facades | accepted | 2026-05-15 | 2026-05-15 | DEC-0026 |
|
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:
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:
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:
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
SystemOSdeve 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
TaskStateeProcessStatejunto. - 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
PrometeuHube firmware ainda acessamos.window_managerdiretamente. - 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:
os.lifecycle().suspend_task(...)
os.fs().mount(...)
os.window().set_focus(...)
Ou, se o design permitir sem duplicar ownership:
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 acessartask_managereprocess_managerque vivem no mesmoSystemOS;- 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:
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 é:
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:
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:
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:
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
- Queremos a sintaxe ideal
os.lifecycle.bla()mesmo que isso force services owners reais, ou aceitamosos.lifecycle().bla()como primeira forma borrow-friendly? quando escrevi os.lifecycle.bla() eu queria mesmo era os.lifecycle().bla() - Quais domínios entram no primeiro corte: só
lifecycleefs, ou tambémwindow? nao precisamos criar nada, mas lifecycle, fs, window e vm sao easy wins no meu ponto de vista create_vm_game_taskecreate_vm_shell_taskpertencem aos.lifecycle(), aos.processes()/os.tasks(), ou a um futuro domínioos.apps()/os.sessions()? vamos de os.session() para esses.tick_vmeinitialize_vmdevem ficar temporariamente na raiz, ou já entrar emos.vm()? isso, os.vm().- Campos como
task_manager,process_manager,window_manager,vm_runtime,fs,memcarddevem 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. - 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:
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 elog(...); 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.