133 lines
8.7 KiB
Markdown
133 lines
8.7 KiB
Markdown
---
|
|
id: AGD-0023
|
|
ticket: studio-play-stop-cartridge-flow
|
|
title: Play/Stop integration agenda for build/pack freshness-gated runtime preparation
|
|
status: in_progress
|
|
created: 2026-04-06
|
|
resolved: 2026-04-06
|
|
decision: DEC-0020
|
|
tags: [studio, play-stop, build, pack, compiler, packer, manifest]
|
|
---
|
|
|
|
## Pain
|
|
|
|
O botão `Play` do Studio hoje só alterna estado visual no shell.
|
|
Ele ainda não aciona um fluxo operacional real para preparar um conjunto executável de artefatos em `build/`.
|
|
|
|
Isso deixa o shell com uma affordance de execução sem pipeline correspondente e sem um contrato claro entre:
|
|
|
|
- Studio shell,
|
|
- compiler build,
|
|
- compiler,
|
|
- packer,
|
|
- e a pasta `build/` do projeto.
|
|
|
|
## Context
|
|
|
|
Domain owner: `studio`.
|
|
Subdomínios referenciados: `compiler`, `packer`, `runtime`.
|
|
|
|
Já existe um `ShipperWorkspace` no Studio e ele hoje chama `BuilderPipelineService.INSTANCE.build(...)`, mas esse fluxo atual é apenas um scratch inicial.
|
|
Na prática, hoje ele está compilando bytecode e não deve ser tratado como o contrato definitivo de preparação de runtime do produto.
|
|
|
|
O objetivo desta agenda não é fechar um pipeline de shipping nem materializar um `cartridge/` separado.
|
|
O escopo desta wave é estritamente o mínimo necessário para o botão `Play` conseguir preparar artefatos rodáveis em `build/`:
|
|
|
|
1. compilar o PBX necessário;
|
|
2. executar o packer necessário;
|
|
3. manter ou regenerar os artefatos de `build/` conforme frescor;
|
|
4. gerar `manifest.json` em `build/`.
|
|
|
|
Essa agenda trata apenas da preparação dos artefatos em `build/`.
|
|
A execução `runtime run cartridge` ou equivalente apontando para `build/` fica em agenda separada dentro da mesma discussion.
|
|
|
|
## Open Questions
|
|
|
|
- [x] O `Play` deve reutilizar exatamente o mesmo pipeline já acionado pelo `ShipperWorkspace`, ou deve haver um service/application layer dedicado para o shell chamar e o workspace apenas consumir?
|
|
- Resposta proposta: `Play` não deve reaproveitar o scratch atual do `ShipperWorkspace`; ele deve orquestrar chamadas explícitas de `build` e `pack`, cada uma com sua própria política de frescor.
|
|
- [x] Os artefatos rodáveis desta wave devem viver em `cartridge/` separado ou no próprio `build/`?
|
|
- Resposta proposta: nesta wave o artifact root runnable deve ser `build/`; não há necessidade de materializar um `cartridge/` separado se o runtime pode consumir o mesmo contrato diretamente de `build/`.
|
|
- [x] Quem decide se é necessário recompilar ou repackar quando o usuário aperta `Play`?
|
|
- Resposta proposta: nesta wave, `Play` sempre chama `build` e `pack`; a política fina de drift/freshness fica explicitamente adiada para uma segunda etapa. Quando essa segunda etapa existir, cada domínio será owner de sua própria política de frescor.
|
|
- [x] Onde deve viver o controle fino de frescor e drift para os artefatos produzidos?
|
|
- Resposta proposta: quando a wave de drift existir, o controle fino viverá em arquivos dedicados por domínio sob `.studio/`, começando por `asset-workspace.json` e `editor-workspace.json`, separados do snapshot principal de restauração.
|
|
- [x] O `manifest.json` runtime-facing deve ser derivado do `prometeu.json` do projeto com normalização adicional do Studio, ou copiado quase diretamente com apenas os campos estritamente runtime-facing?
|
|
- Resposta proposta: o `manifest.json` deve ser sempre gerado de forma determinística em `build/`, a partir do build corrente e do owner metadata do projeto, sem cópia por conveniência.
|
|
- [x] Como o shell distinguirá falha de build, falha de pack e falha de manifest para refletir estado útil no `Play/Stop`?
|
|
- Resposta proposta: para o `Play`, basta distinguir `success` e `failed`; logs detalhados das operações devem acompanhar o resultado. `build` falhando bloqueia `pack`, e `manifest` só roda depois do sucesso do build/pack desta wave.
|
|
|
|
## Options
|
|
|
|
### Option A - `Play` sempre chama `build` e `pack`, e drift fica para uma wave posterior
|
|
- **Approach:** Fazer o shell chamar explicitamente `build` e `pack` em toda execução de `Play`; nesta wave não há reuse por drift/freshness, apenas execução determinística com logs e geração final de `manifest.json`.
|
|
- **Pro:** Destrava a integração do `Play` com o menor contrato correto, sem antecipar um sistema de freshness ainda não normatizado.
|
|
- **Con:** Pode refazer trabalho desnecessário em execuções sucessivas até a wave de drift existir.
|
|
- **Maintainability:** Boa, porque mantém o `Play` simples agora e deixa a otimização para uma agenda própria depois.
|
|
|
|
### Option B - `Play` inspeciona artefatos existentes e decide por conta própria se pode seguir
|
|
- **Approach:** O shell observa presença ou timestamps de artefatos em `build/` e tenta inferir se basta reutilizar o que já existe.
|
|
- **Pro:** Menos modelagem inicial de metadata e contratos.
|
|
- **Con:** Move para o shell uma inteligência que pertence aos domínios de compiler e packer, além de abrir espaço para reuse incorreto sob drift parcial do workspace.
|
|
- **Maintainability:** Fraca, porque o `Play` vira owner implícito de políticas que não são dele.
|
|
|
|
## Discussion
|
|
|
|
O ponto central aqui não é apenas "rodar compile + packer".
|
|
O problema real é separar claramente:
|
|
|
|
- a orquestração do `Play`,
|
|
- a responsabilidade de `build`,
|
|
- a responsabilidade de `pack`,
|
|
- e a futura política de frescor de cada artefato.
|
|
|
|
Se o `Play` inferir por conta própria se precisa rebuildar ou repackar, o shell passa a absorver conhecimento que pertence a outros domínios.
|
|
Isso cria uma fronteira errada: o shell deixa de ser apenas o caller de operações e passa a ser o árbitro de drift do projeto.
|
|
|
|
Ao mesmo tempo, modelar agora um sistema fino de drift adicionaria complexidade antes da própria integração básica do `Play` existir.
|
|
Por isso, esta agenda fecha a wave 1 com execução sempre explícita e adia a otimização de freshness para uma agenda própria.
|
|
|
|
O contrato mais limpo é:
|
|
|
|
1. `Play` pede `build`;
|
|
2. `build` executa e retorna `success` ou `failed`, acompanhado de logs;
|
|
3. `Play` pede `pack`;
|
|
4. `pack` executa e retorna `success` ou `failed`, acompanhado de logs;
|
|
5. `manifest.json` é sempre regenerado em `build/` a partir do build corrente e dos metadados do projeto;
|
|
6. `Play` só verifica sucesso ou falha dessas operações antes de seguir para a execução.
|
|
|
|
Os constraints já visíveis no repositório reforçam esse recorte:
|
|
|
|
- o compiler atual escreve `build/program.pbx`;
|
|
- o packer atual escreve `build/assets.pa` e companions de tooling, e o spec do packer afirma explicitamente que cartridge assembly não pertence ao domínio `packer`;
|
|
- os projetos de teste já mostram `build/` contendo `program.pbx`, `assets.pa` e companions;
|
|
- `ProjectLocalStudioSetup` já está carregado na `StudioProjectSession`, então o shell já possui o owner correto para coordenar preparation + future run sem precisar deduzir drift por presença oportunista de arquivo.
|
|
|
|
Isso torna a fronteira recomendada mais concreta:
|
|
|
|
1. `build/` é o artifact root runnable desta wave;
|
|
2. compiler e packer continuam donos de seus artefatos dentro de `build/`;
|
|
3. `Play` não usa presença de arquivo como regra de validade;
|
|
4. drift e freshness ficam explicitamente fora do escopo desta wave e poderão viver em arquivos dedicados por domínio sob `.studio/`;
|
|
5. o shell avança apenas quando `build`, `pack` e `manifest` reportarem sucesso.
|
|
|
|
A recomendação inicial desta agenda é:
|
|
|
|
1. fazer `Play` chamar explicitamente `build` e `pack`;
|
|
2. manter `build` e `pack` como operações domain-owned com logs e resultado binário de sucesso/falha nesta wave;
|
|
3. adiar o controle fino de drift/freshness para uma agenda própria posterior;
|
|
4. promover `build/` como artifact root runnable desta wave;
|
|
5. gerar `manifest.json` em `build/` sempre a partir do build corrente;
|
|
6. tratar o resultado de cada operação como contrato explícito para o `Play`, sem heurística oportunista baseada apenas em presença de arquivo.
|
|
|
|
## Resolution
|
|
|
|
Próximo passo sugerido: fechar uma decision de `studio` que trave o fluxo de preparação do `Play/Stop` com estas amarras normativas já explícitas:
|
|
|
|
1. `Play` é apenas o orquestrador de `build`, `pack` e `manifest`;
|
|
2. nesta wave, `build` sempre executa quando chamado pelo `Play`;
|
|
3. nesta wave, `pack` sempre executa quando chamado pelo `Play`, e só é chamado se `build` tiver sucesso;
|
|
4. o artifact root runnable desta wave é `build/`, não `cartridge/`;
|
|
5. `manifest.json` é sempre gerado deterministicamente em `build/`, a partir do build corrente, e não copiado por conveniência;
|
|
6. freshness e drift ficam fora do escopo desta wave e, quando tratados, usarão arquivos dedicados por domínio sob `.studio/`, como `asset-workspace.json` e `editor-workspace.json`;
|
|
7. `Play` só segue adiante quando as operações necessárias reportarem sucesso.
|