prometeu-studio/discussion/workflow/agendas/AGD-0024-studio-play-stop-runtime-run-cartridge.md

129 lines
9.5 KiB
Markdown

---
id: AGD-0024
ticket: studio-play-stop-cartridge-flow
title: Play/Stop integration agenda for runtime execution from build using project runtime setup
status: in_progress
created: 2026-04-06
resolved: 2026-04-06
decision: DEC-0021
tags: [studio, runtime, play-stop, build, process, project-setup]
---
## Pain
Mesmo depois que o Studio conseguir preparar `build/`, o botão `Play` continuará incompleto sem um contrato claro para executar o runtime configurado no projeto contra esse artifact root.
Hoje o caminho do runtime já existe em `.studio/setup.json` via `ProjectLocalStudioSetup.prometeuRuntimePath`, mas esse valor ainda não participa de nenhuma execução real no shell.
Sem essa definição, o `Play/Stop` corre o risco de virar:
- um botão que prepara `build/` mas não executa nada;
- ou um launcher improvisado, sem owner claro para processo, logs, lifecycle e falhas.
## Context
Domain owner: `studio`.
Subdomínios referenciados: `runtime`.
O Studio já carrega `ProjectLocalStudioSetup` na `StudioProjectSession`.
Portanto o runtime configurado por projeto já está disponível para consumo em runtime de aplicação.
Após a decisão `DEC-0020`, esta agenda passa a assumir explicitamente que:
- `Play` prepara `build/` como artifact root runnable;
- `manifest.json` é gerado em `build/`;
- não há `cartridge/` separado nesta wave.
O comando desejado pelo usuário é conceitualmente:
`runtime run build`
usando o runtime configurado no projeto atual.
Esta agenda não rediscute preparação de `build/`.
Ela assume a saída de `DEC-0020` como pré-condição e foca no segundo passo do `Play`: iniciar, observar e interromper o processo de runtime.
Também há um constraint de UX desta wave:
- ao apertar `Play`, o usuário deverá ser levado para o futuro `DebuggerWorkspace`, mesmo que essa surface ainda não esteja construída;
- até essa surface existir, os logs do runtime precisarão "ficar voando", isto é, viver provisoriamente fora do destino final pretendido;
- a etapa de `pack` usada por `Play` deve preservar seu ciclo de validação antes da execução do runtime;
- os logs de `build` e `pack` também devem convergir para o destino do debugger, porque é nessa surface que o usuário verá falhas de compilação, validação ou packing durante o fluxo do `Play`.
Também há um constraint de escopo nesta wave:
- checks adicionais de preflight antes do `build`, como arquivos do editor ainda não salvos, não entram agora;
- quando essa wave futura existir, ela deverá bloquear o `Play` antes do `build` com erro explícito, em vez de ser tratada como detalhe implícito de runtime.
## Open Questions
- [x] O `Play` deve falhar imediatamente quando `prometeuRuntimePath` estiver ausente, ou o shell deve oferecer algum repair path explícito antes de abortar?
- Resposta proposta: nesta wave, o `Play` deve falhar imediatamente com erro explícito quando `prometeuRuntimePath` estiver ausente, inválido, inexistente ou não executável; repair path guiado fica para uma wave posterior.
- [x] O Studio deve executar o runtime diretamente pelo binário configurado, ou por um wrapper/comando fixo resolvido a partir desse path?
- Resposta proposta: o Studio deve executar como processo externo o binário configurado em `ProjectLocalStudioSetup.prometeuRuntimePath`, apontando para `build/` e usando o subcomando `run` nesta wave; uma futura wave de debugger poderá trocar esse subcomando para `debug`.
- [x] O `Stop` deve encerrar apenas o processo de runtime ativo iniciado pelo shell atual, ou também limpar algum estado transitório adicional no Studio?
- Resposta proposta: `Stop` deve encerrar apenas o processo de runtime ativo iniciado pelo `Play` atual; não deve limpar estado transitório adicional além do lifecycle desse processo.
- [x] Onde os logs de stdout/stderr do runtime devem viver nesta primeira wave: activity feed, shipper logs, uma surface dedicada, ou combinação mínima dessas superfícies?
- Resposta proposta: o destino final dos logs deve ser o futuro `DebuggerWorkspace`, e o `Play` deve navegar para essa surface ao iniciar a execução; até ela existir, stdout/stderr e também os logs de `build`/`pack` ficam provisoriamente em uma solução transitória desacoplada, enquanto o Activity Feed recebe apenas eventos resumidos de início, sucesso de término e falha.
- [x] Como o shell deve serializar múltiplos cliques em `Play`: ignorar enquanto já está rodando, reiniciar, ou encadear stop + rerun?
- Resposta proposta: enquanto já houver runtime ativo iniciado pelo shell atual, cliques adicionais em `Play` devem ser ignorados até o processo sair ou o usuário apertar `Stop`.
- [x] O `pack` usado pelo `Play` pode empacotar diretamente, ou deve preservar o ciclo de validação antes da execução do runtime?
- Resposta proposta: o `pack` usado pelo `Play` deve preservar seu ciclo de validação antes da execução; se a validação bloquear o pack, o runtime não deve iniciar.
- [x] Checks extras antes do `build`, como arquivos não salvos no editor, entram nesta wave?
- Resposta proposta: não; preflight adicional de `build`, incluindo arquivos ainda não salvos, fica explicitamente para uma wave posterior e não altera o contrato desta agenda.
- [x] A execução da agenda 24 deve validar explicitamente a existência de `build/manifest.json` antes do spawn, ou isso fica implícito pelo sucesso da preparação?
- Resposta proposta: isso fica implícito pelo sucesso da preparação definida em `DEC-0020`; a agenda 24 não adiciona check redundante de existência de `manifest.json` antes do spawn.
## Options
### Option A - Play/Stop controla um processo único de runtime do projeto ativo
- **Approach:** O shell resolve o runtime configurado no `ProjectLocalStudioSetup`, executa diretamente o binário configurado contra `build/` como processo do projeto ativo, mantém handle desse processo e usa `Stop` para encerrar exatamente esse processo.
- **Pro:** O comportamento do botão fica simples, previsível e diretamente alinhado ao modelo visual de toggle.
- **Con:** Exige que o Studio introduza ownership explícito de processo, logs e cleanup, em vez de só alternar estado visual.
- **Maintainability:** Boa, porque o shell passa a ter um contrato único de execução por projeto e um lifecycle claro.
### Option B - Play delega a execução ao workspace ou a um launcher externo sem handle direto no shell
- **Approach:** O shell apenas dispara uma ação indireta e considera-se "running" sem possuir o processo como first-class state próprio.
- **Pro:** Menor acoplamento inicial entre shell e camada de processo.
- **Con:** O `Stop` fica semanticamente fraco ou enganoso, porque o shell não controla de verdade o processo que diz estar executando.
- **Maintainability:** Fraca, porque o toggle visual deixa de corresponder ao lifecycle real da execução.
## Discussion
O ponto mais importante desta agenda é alinhar o significado de `Stop`.
Se o shell não possui o processo de runtime como state explícito, o botão vira só uma fantasia visual.
Como o runtime path já é project-local setup carregado na sessão, o Studio já tem o owner certo para resolver o binário configurado.
O que falta é explicitar o contrato operacional:
1. validar que o runtime configurado existe e é executável;
2. executar `build`;
3. executar a validação de `pack`;
4. executar `pack` somente quando a validação permitir;
5. enviar os logs de `build` e `pack` para a surface de debugger/logs da execução;
6. rodar como processo externo o runtime configurado contra `build/` no contexto do projeto ativo, usando `run` nesta wave;
7. capturar stdout/stderr;
8. refletir running/stopped/failure no shell;
9. interromper o processo correto quando o usuário apertar `Stop`.
A execução do runtime nesta agenda confia no contrato de preparação anterior.
Portanto, esta wave não introduz preflight redundante para verificar novamente a existência de `build/manifest.json` antes do spawn.
A recomendação inicial desta agenda é:
1. fazer o shell ser owner de um único runtime-process handle por projeto ativo;
2. resolver o comando a partir de `ProjectLocalStudioSetup.prometeuRuntimePath`;
3. falhar de forma explícita quando o runtime do projeto estiver ausente ou inválido;
4. definir `Stop` como término do processo iniciado pelo `Play` atual, e não como reset genérico de UI;
5. ignorar novo `Play` enquanto o processo atual ainda estiver rodando;
6. preservar a validação de pack antes do pack efetivo na preparação do `Play`;
7. tratar o futuro `DebuggerWorkspace` como destino canônico da execução e dos logs de runtime, `build` e `pack`;
8. enquanto o `DebuggerWorkspace` não existir, manter stdout/stderr e logs de preparação em uma solução transitória, usando o Activity Feed apenas para sinais resumidos de lifecycle;
9. deixar checks extras de preflight antes do `build`, como arquivos não salvos, fora desta wave;
10. fixar `run` como o subcomando de execução desta wave, deixando `debug` para uma futura wave de debugger;
11. confiar no sucesso da preparação anterior sem adicionar preflight redundante de `manifest.json` antes do spawn.
## Resolution
Próximo passo sugerido: fechar uma decision de `studio` que defina ownership de processo para `Play/Stop`, preserve o ciclo de validação + pack antes da execução do runtime, fixe a execução como processo externo do runtime configurado usando `run` contra `build/`, trate o `DebuggerWorkspace` como destino futuro da sessão de execução e explicite que checks extras de preflight do `build` ficam para uma wave posterior.