prometeu-studio/discussion/workflow/agendas/AGD-0010-studio-code-editor-workspace-foundations.md

12 KiB

id ticket title status created resolved decision tags
AGD-0010 studio-code-editor-workspace-foundations Iniciar foundations do Code Editor no Studio sem LSP open 2026-03-30
studio
editor
workspace
multi-frontend
lsp-deferred

Pain

O shell do Studio ja assume Code Editor como parte do baseline workspace set, mas a implementacao atual do EditorWorkspace ainda e apenas um CodeArea com texto hardcoded e botoes sem modelo real de documento, tabs, arquivos, dirty state ou sessao de projeto.

Ao mesmo tempo, queremos iniciar os trabalhos do editor agora, com foco em UI e infraestrutura robusta para varios frontends, mas sem cair em uma dependencia prematura de LSP.

Sem fechar a boundary agora, a implementacao pode desviar para dois extremos ruins:

  • o Studio virar uma casca quase vazia que depende de cada frontend ate para abrir, salvar e manter buffers;
  • ou o Studio absorver semantica demais e virar uma segunda autoridade sobre parsing, diagnosticos e modelo de compilacao.

Context

Domain owner: studio Owner surface: docs/specs/studio Cross-domain input: compiler

Superficies relevantes hoje:

  • docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md ja define Code Editor como workspace baseline do shell;
  • docs/specs/studio/2. Studio UI Foundations Specification.md exige workspaces com composicao root, event bus tipado, lifecycle-managed controls e infra reutilizavel;
  • prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java hoje monta um CodeArea simples sem modelo de arquivos do projeto;
  • prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java ja consome FrontendRegistryService e FrontendSpec, o que mostra que o Studio ja reconhece multiplos frontends e source roots por linguagem;
  • prometeu-compiler/.../FrontendSpec.java ja modela languageId, allowedExtensions, sourceRoots, caseSensitive e versoes de stdlib;
  • o compiler hoje ainda descobre e le fontes diretamente do filesystem: LoadSourcesPipelineStage faz walkFileTree(...) nos sourceRoots, BuilderPipelineContext.compilerContext(...) instancia SourceProviderFactory.filesystem(), e SourceHandle le bytes com Files.readAllBytes(path);
  • docs/roadmaps/lsp/ ja existe como trilha separada, mas esta wave quer editor sem depender de LSP;
  • o precedente do packer fixa uma boa disciplina de ownership, mas ele nao deve ser copiado mecanicamente para o editor sem discutir a diferenca entre semantica de dominio e sessao generica de edicao.

O ponto mais sensivel desta agenda e justamente essa diferenca:

  • no packer, Studio nao deve reinventar semantica de asset, snapshots operacionais ou write lanes de dominio;
  • no editor, leitura/escrita de arquivos fonte, dirty tracking, buffers em memoria e snapshots documentais fazem parte da propria experiencia do workspace e nao sao, por si so, semantica de linguagem.

Direcao adicional ja explicitada para a UX:

  • o editor deve seguir um baseline proximo ao modelo do IntelliJ;
  • a ala esquerda deve ser um Project Navigator com arquivos/pastas relevantes do projeto;
  • a area central deve ter tabs de arquivos abertos no topo e o editor rico no corpo principal;
  • a regiao inferior deve ser um helper persistente para prompts, tips e feedback contextual sobre o codigo atual, funcionando mais como advanced editor log do que como console cru.

Open Questions

  • Qual e o seam normativo para ligar document snapshots do editor ao compiler: substituir SourceProviderFactory.filesystem() por provider de sessao, ou introduzir uma etapa explicita que materializa uma visao congelada de documentos antes do pipeline?
  • O primeiro wave do editor deve nascer com tabs multiplas e sessao multi-documento completa, ou tabs multiplas com uma politica mais simples de documentos ativos/carregados?
  • Como o EditorWorkspace descobre quais arquivos e source roots sao editaveis a partir de ProjectReference.languageId e FrontendSpec?
  • Quem detecta modificacoes externas em arquivos abertos e como o conflito entre disco e buffer em memoria deve aparecer para o usuario?
  • Alem do baseline ja aceito (Project Navigator, tabs, editor central, helper inferior), a primeira wave tambem deve incluir outline ou status bar, ou esses elementos ficam explicitamente para depois?
  • Como preservar uma UI consistente entre linguagens diferentes sem forcar cada frontend a carregar seu proprio mini-editor completo?
  • O que fica explicitamente fora desta wave por ausencia de LSP: autocomplete, go to definition, semantic diagnostics ao digitar, symbols, rename, code actions?

Options

Option A - Studio como casca pura; frontend/backends fazem o resto

  • Approach: O Studio hospeda a area visual do editor, mas leitura, escrita, buffers, snapshots e demais operacoes relevantes ficam delegadas a adaptadores por linguagem ou a servicos externos.
  • Pro: Mantem o Studio "leve" e minimiza responsabilidade local.
  • Con: Duplica infraestrutura generica em cada frontend, acopla UX basica a backend de linguagem e torna dificil sustentar uma experiencia coerente multi-FE sem LSP.
  • Maintainability: Fraca. A boundary fica formalmente limpa, mas o custo reaparece como fragmentacao de sessao, inconsistencias de UX e adaptadores repetidos.

Option B - Studio possui sessao generica de documentos; frontends possuem semantica

  • Approach: O Studio passa a possuir uma camada generica de editor para descoberta de arquivos, open/save, dirty tracking, tabs, estado ativo, deteccao de mudanca externa e snapshots imutaveis de documento em memoria; frontends consomem essa camada como entrada para highlighting, parsing, diagnosticos e outras features atuais ou futuras.
  • Pro: Cria uma base robusta para varios frontends mesmo sem LSP, evita duplicacao de infra generica e mantem a semantica de linguagem fora do workspace visual.
  • Con: Exige disciplina para nao confundir snapshot documental com snapshot semantico do compiler e para nao deixar a camada generica vazar regras de linguagem.
  • Maintainability: Forte. A separacao entre sessao de edicao e semantica de linguagem fica clara e expansivel.

Option C - Cada frontend possui seu proprio stack de editor end-to-end

  • Approach: O Studio oferece apenas um host de workspace, e cada frontend implementa seu proprio editor, file model, snapshots e event wiring do zero.
  • Pro: Maxima liberdade por linguagem.
  • Con: Destrói a chance de um framework comum de editor, duplica problema de tabs/buffers/save/conflicts e torna a shell dependente de N mini-produtos locais.
  • Maintainability: Fraca. Funciona para prototipos isolados, mas nao para um Studio que quer suportar varios FEs sob uma UX comum.

Option D - Esperar LSP e desenhar o editor em torno dele

  • Approach: Adiar a infra editorial mais seria ate que exista um backend LSP suficientemente funcional e modelar o editor a partir desse contrato.
  • Pro: Pode reduzir retrabalho se o LSP for a unica fronteira desejada.
  • Con: Conflita com o objetivo desta wave, atrasa o editor, e ainda nao resolve ownership de file IO, buffers e dirty state, que continuam existindo mesmo com LSP.
  • Maintainability: Media para baixa. O LSP ajuda na semantica, mas nao substitui a sessao generica de edicao.

Discussion

O precedente do packer e util, mas ele nao responde sozinho a pergunta desta agenda.

No packer, a semantica de dominio e forte:

  • identidade de asset;
  • validacao;
  • write lane;
  • snapshots operacionais;
  • causality de eventos.

Nessa area, faz sentido Studio atuar mais como adaptador editorial do que como autoridade.

No editor de codigo, porem, existe uma camada anterior a qualquer semantica de linguagem:

  • abrir arquivo;
  • manter buffer em memoria;
  • controlar dirty state;
  • salvar em disco;
  • alternar tabs;
  • versionar snapshots documentais;
  • reagir a mudancas externas;
  • expor um modelo de sessao que qualquer FE consiga consumir.

Essas responsabilidades nao sao "semantica de compiler". Sao responsabilidades normais de um editor. Se o Studio se recusar a possui-las, cada frontend ou integracao futura precisara reinventar a mesma infraestrutura.

Do ponto de vista de UX, a direcao mais solida e assumir um baseline de tres regioes dentro do EditorWorkspace:

  1. Project Navigator na esquerda
  2. Editor Workarea no centro, com tabs acima e editor no corpo
  3. Editor Helper Panel na base, para tips, prompts, hints e feedback contextual

Esse painel inferior merece cuidado de nomenclatura e ownership. Ele nao deve nascer como "console generico" nem como dumping ground de logs tecnicos. Melhor trata-lo como uma superficie editorial guiada pelo contexto do documento ativo.

Sugestao de papel para esse helper:

  • mostrar hints sobre arquivo, linguagem e estado do documento;
  • receber mensagens de parse/local validation quando existirem;
  • explicar bloqueios de save, conflitos de disco e prompts do editor;
  • no futuro, acomodar saidas de LSP ou FE sem acoplar a shell global a isso.

Em outras palavras: ele deve ser um assistant/log de workspace, nao um substituto do painel global Activity e nao um terminal cru.

O boundary mais saudavel parece ser:

  1. o Studio possui a sessao generica de documentos e a UX editorial comum;
  2. os frontends recebem snapshots documentais imutaveis como entrada;
  3. parsing, name resolution, diagnostics, semantic tokens, completions e afins continuam fora da camada generica do editor;
  4. LSP, quando existir, entra como um consumidor/provedor de semantica sobre essa base, nao como substituto da base.

O estado atual do compiler reforca essa necessidade. Hoje o build pipeline ainda assume filesystem como source of truth imediata:

  • os arquivos sao descobertos por crawl direto nos sourceRoots;
  • o BuilderPipelineContext nasce com SourceProviderFactory.filesystem();
  • cada SourceHandle le bytes do Path canonico.

Isso significa que, se quisermos uniformizar Studio, FE services e LSP futuro em torno de uma mesma visao documental, precisamos introduzir explicitamente uma camada de document snapshot antes do consumo pelo pipeline. O lado bom e que ja existe um seam util: SourceProviderFactory nao esta hardcoded em todos os callsites e ja sugere providers alternativos, inclusive in-memory.

Isso tambem ajuda com a meta de varios FEs:

  • FrontendSpec ja informa roots e extensoes;
  • o EditorWorkspace pode montar a superficie a partir disso;
  • e cada linguagem fica livre para plugar servicos sem destruir o modelo editorial comum.

Resolution

Recommended direction: seguir com Option B.

A agenda deve convergir para uma decisao com os seguintes fechamentos:

  1. o Studio deve possuir uma camada generica de document/session para o Code Editor;
  2. essa camada pode ler e escrever arquivos fonte e manter snapshots documentais em memoria;
  3. essa camada nao deve possuir semantica de linguagem, parsing autoritativo ou diagnosticos como responsabilidade primaria;
  4. frontends devem consumir snapshots documentais do editor por um contrato explicito, imutavel e versionado;
  5. como o compiler hoje ainda le do filesystem, a decisao precisa fechar uma etapa/seam concreta para injetar document snapshots antes do pipeline, uniformizando a entrada de Studio, FE services e LSP futuro;
  6. LSP fica explicitamente fora do primeiro wave, mas a modelagem precisa deixar caminho limpo para ele;
  7. a primeira wave do editor deve normatizar explicitamente o baseline visual do workspace: Project Navigator na esquerda, tabs no topo da area central, editor rico no corpo e Editor Helper Panel inferior reservado;
  8. o Editor Helper Panel nasce passivo na primeira wave, como espaco reservado para prompts, tips e feedback contextual, sem obrigar interatividade imediata.

Next step suggestion: converter esta agenda em uma decision que feche o boundary entre EditorWorkspace, sessao documental do Studio e servicos de frontend, incluindo o escopo exato da primeira wave de UI sem LSP.