diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 91087884..a6a471c5 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":42,"PLN":111,"LSN":58,"CLSN":1}} +{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":43,"PLN":117,"LSN":58,"CLSN":1}} {"type":"discussion","id":"DSC-0065","status":"open","ticket":"multi-frontend-avoid-premature-abstractions","title":"Evitar abstracoes prematuras na preparacao multi-frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","frontend","architecture","multi-frontend","simplicity"],"agendas":[{"id":"AGD-0068","file":"AGD-0068-multi-frontend-avoid-premature-abstractions.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0064","status":"open","ticket":"multi-frontend-architectural-tests","title":"Testes arquiteturais para fronteiras multi-frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","frontend","architecture","tests","multi-frontend"],"agendas":[{"id":"AGD-0067","file":"AGD-0067-multi-frontend-architectural-tests.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0063","status":"open","ticket":"multi-frontend-synthetic-test-frontend","title":"Frontend sintetico de teste para provar neutralidade do pipeline","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","frontend","tests","backend","multi-frontend"],"agendas":[{"id":"AGD-0066","file":"AGD-0066-multi-frontend-synthetic-test-frontend.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} @@ -8,7 +8,7 @@ {"type":"discussion","id":"DSC-0059","status":"open","ticket":"multi-frontend-common-lifecycle","title":"Extrair lifecycle comum das responsabilidades do frontend PBS","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","lifecycle","backend","multi-frontend"],"agendas":[{"id":"AGD-0062","file":"AGD-0062-multi-frontend-common-lifecycle.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0058","status":"open","ticket":"multi-frontend-serializable-ir","title":"Manter a IR comum serializavel por design","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","ir","backend","serialization","multi-frontend"],"agendas":[{"id":"AGD-0061","file":"AGD-0061-multi-frontend-serializable-ir.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0057","status":"open","ticket":"multi-frontend-frontend-backend-contract","title":"Estabilizar contrato entre frontend e backend comum","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","ir","backend","multi-frontend"],"agendas":[{"id":"AGD-0060","file":"AGD-0060-multi-frontend-frontend-backend-contract.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0056","status":"open","ticket":"multi-frontend-remove-pbs-branches","title":"Remover verificacoes explicitas de PBS do codigo comum","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","studio","frontend","coupling","multi-frontend"],"agendas":[{"id":"AGD-0059","file":"AGD-0059-multi-frontend-remove-pbs-branches.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0056","status":"in_progress","ticket":"multi-frontend-remove-pbs-branches","title":"Generalizar o contrato LSP/editorial para frontends","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","studio","frontend","coupling","multi-frontend"],"agendas":[{"id":"AGD-0059","file":"AGD-0059-multi-frontend-remove-pbs-branches.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0042","file":"DEC-0042-frontend-editorial-language-service-contract-for-lsp.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0059"}],"plans":[{"id":"PLN-0111","file":"PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0112","file":"PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0113","file":"PLN-0113-migrate-completion-to-generic-frontend-models.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0114","file":"PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0115","file":"PLN-0115-migrate-signature-help-to-generic-frontend-models.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0116","file":"PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]}],"lessons":[]} {"type":"discussion","id":"DSC-0055","status":"done","ticket":"multi-frontend-compiler-vs-language-services","title":"Separar compilacao de servicos editoriais de frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","lsp","editor","frontend","multi-frontend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0056","file":"discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]} {"type":"discussion","id":"DSC-0054","status":"done","ticket":"multi-frontend-provider-contract","title":"Introduzir provider completo de frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","frontend","registry","multi-frontend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0055","file":"discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]} {"type":"discussion","id":"DSC-0053","status":"open","ticket":"pbs-lsp-call-and-type-hierarchy","title":"PBS LSP Call and Type Hierarchy","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","call-hierarchy","type-hierarchy"],"agendas":[{"id":"AGD-0056","file":"AGD-0056-pbs-lsp-call-and-type-hierarchy.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/agendas/AGD-0059-multi-frontend-remove-pbs-branches.md b/discussion/workflow/agendas/AGD-0059-multi-frontend-remove-pbs-branches.md index 966bf7e9..5773d904 100644 --- a/discussion/workflow/agendas/AGD-0059-multi-frontend-remove-pbs-branches.md +++ b/discussion/workflow/agendas/AGD-0059-multi-frontend-remove-pbs-branches.md @@ -1,78 +1,164 @@ --- id: AGD-0059 ticket: multi-frontend-remove-pbs-branches -title: Remover verificacoes explicitas de PBS do codigo comum -status: open +title: Generalizar o contrato LSP/editorial para frontends +status: accepted created: 2026-07-15 resolved: decision: tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] --- -# Agenda - Remover verificacoes explicitas de PBS do codigo comum +# Agenda - Generalizar o contrato LSP/editorial para frontends -## Objetivo +## Pain Domain owner: `compiler/general`, com impacto em `studio` e `compiler/pbs`. -Definir uma auditoria e remocao incremental de branches, instanciacoes e chamadas estaticas PBS em codigo comum. +O PBS ja esta majoritariamente centrado no proprio frontend. A auditoria inicial nao confirmou um problema amplo de codigo comum decidindo comportamento por PBS. -## Contexto atual +O acoplamento que ainda importa e mais especifico: o `CompilerLanguageServiceBridge` do LSP usa diretamente classes do frontend PBS para completion, hover, signature help, semantic tokens e leitura editorial. Isso impede que outro frontend plugado no registry ofereca LSP/editor assistance sem repetir ou bifurcar esse caminho. -O documento de alinhamento aponta ocorrencias como `"pbs"`, `PBSDefinitions`, `PBSFrontendPhaseService`, `PBSFrontend`, `PbsParser`, `PbsSemantic` e `languageId`. A primeira busca no repo confirma ocorrencias espalhadas em docs, testes, frontend PBS, build pipeline e Studio. +## Context -## Escopo +PBS e a linguagem default do produto hoje. Usar PBS como fallback quando o usuario nao escolhe linguagem e valido e deve continuar permitido. Isso inclui defaults de criacao de projeto e bootstrap de registry/composition root enquanto PBS for o unico frontend concreto. -- Classificar ocorrencias como internas ao PBS, composition root, testes PBS ou referencias indevidas. -- Substituir referencias indevidas por provider, spec, capability ou servico registrado. -- Manter excecoes explicitas documentadas. +A verificacao local mostrou este estado: -## Fora de escopo +- referencias PBS dentro de `prometeu-compiler/frontends/prometeu-frontend-pbs/**` sao internas ao frontend e nao sao problema; +- testes, fixtures `.pbs`, templates PBS, semantic keys PBS e registro da extensao VS Code para `.pbs` sao referencias esperadas; +- `ProjectLanguageCatalogService` ja constroi templates a partir de `FrontendRegistryService.listProviders()`; +- `ProjectCatalogService` ainda usa `"pbs"` em overloads simples de `createProject(...)`, mas isso representa default/fallback e nao deve ser tratado como violacao; +- `FrontendRegistryService` registra `PBSFrontendProvider` como default concreto, o que pertence ao bootstrap/composition root atual; +- `CompilerLanguageServiceBridge` ainda importa `PBSFrontendLanguageService`, `PBSFrontendPhaseService`, `p.studio.compiler.pbs.semantics.*` e tipos AST PBS diretamente. -- Remover constantes PBS internas do proprio frontend. -- Alterar templates explicitamente PBS. -- Renomear packages. +Portanto a agenda deve deixar de ser uma busca generica por `"pbs"` e passar a discutir qual contrato LSP/editorial generico os frontends devem implementar, em etapas, para que PBS seja apenas um provider desse contrato. -## Arquivos e componentes a inspecionar +## Open Questions -- `prometeu-app/src/main/java/p/studio/AppContainer.java` -- `prometeu-studio/src/main/java/p/studio/window/NewProjectWizard.java` -- `prometeu-studio/src/main/java/p/studio/projects/...` -- `prometeu-compiler/prometeu-build-pipeline/...` -- `prometeu-compiler/frontends/prometeu-frontend-pbs/...` -- testes que importam `p.studio.compiler.pbs...` +- [x] Qual e o menor contrato editorial generico que um frontend precisa expor para o LSP v1 dentro do `languageService()` opcional: semantic tokens, completion, hover e signature help em uma superficie agregada ou como capacidades internas declaraveis? + - Resposta: manter `FrontendProvider.languageService()` como superficie opcional agregada; dentro dela, expor capacidades editoriais pequenas e opcionais para semantic tokens, completion, hover e signature help. +- [x] O contrato deve viver em `prometeu-frontend-api`, `prometeu-compiler-core`, ou em um modulo especifico de language services compartilhado? + - Resposta: o contrato generico deve viver em `prometeu-frontend-api`, porque e a fronteira entre frontends e consumidores comuns. O frontend nao deve depender de `prometeu-lsp`, e tipos editoriais nao devem ser empurrados para `compiler-core` sem necessidade. +- [x] O LSP deve consumir apenas tipos genericos de frontend, ou pode manter um adapter PBS temporario enquanto as interfaces sao extraidas em etapas? + - Resposta: o estado final deve consumir apenas tipos genericos de frontend; adapters PBS temporarios sao aceitaveis apenas como migracao por capacidade. +- [x] Como o pipeline deve fornecer AST/snapshot/editorial context sem expor `PbsAst.File` e `PBSFrontendPhaseService.semanticReadSurface(...)` ao LSP? + - Resposta: o LSP deve pedir capacidades ao language service do provider selecionado. O provider/frontend fica responsavel por produzir ou consumir o snapshot editorial necessario, sem expor AST PBS ou semantic read surface PBS ao caminho comum do LSP. +- [x] Como representar tipos hoje PBS-specific, como `PbsEditorialCompletionCandidate`, `PbsEditorialResolvedSymbol`, `PbsEditorialSignatureHelp` e `PbsEditorialSymbolKind`, em modelos genericos sem perder informacao necessaria? + - Resposta: criar modelos genericos pequenos, como `FrontendCompletionCandidate`, `FrontendHover`, `FrontendSignatureHelp`, `FrontendSignature`, `FrontendSymbolKind` e, se necessario, `FrontendDocumentation`. PBS mapeia seus tipos internos para esses modelos. +- [x] Quais capacidades devem ser opcionais por frontend para permitir frontends compile-only sem quebrar o LSP? + - Resposta: todas as capacidades editoriais sao opcionais. `compiler()` continua obrigatorio; `languageService()` continua opcional; cada feature editorial deve ter fallback deterministico quando ausente. +- [x] Quais referencias PBS devem ser registradas como excecoes permanentes ou temporarias: default/fallback, composition root, testes, templates, fixtures, extensao VS Code e frontend PBS interno? + - Resposta: sao permitidos frontend PBS interno, testes PBS, fixtures `.pbs`, templates PBS, VS Code `.pbs`, semantic keys PBS, PBS como default/fallback quando o usuario nao escolhe linguagem e bootstrap/composition root enquanto PBS for o frontend concreto default. Nao sao permitidos imports PBS no LSP comum, instanciacao PBS em common compiler/build/studio fora de provider/composition root, nem fallback PBS para `languageId` desconhecido. -## Alteracoes propostas +## Options -Opcao A: auditoria textual primeiro, seguida de PRs pequenos por area. +### Option A - Interface editorial generica em uma etapa -Opcao B: criar teste arquitetural antes e usar falhas para guiar remocao. +- **Approach:** definir de uma vez uma interface generica para semantic tokens, completion, hover, signature help, documentos editoriais e modelos de retorno; migrar o LSP para consumir apenas essa interface. +- **Pro:** remove o acoplamento PBS do LSP em um unico corte conceitual. +- **Con:** alto risco de abstrair demais antes de existir um segundo frontend real; pode forcar modelos genericos grandes e instaveis. +- **Maintainability:** boa se o contrato sair correto, mas fragil se a primeira versao tentar cobrir casos ainda desconhecidos. -Recomendacao inicial: fazer auditoria textual e classificar em tabela curta antes de alterar; em seguida adicionar teste arquitetural para impedir regressao. +### Option B - Extracao incremental por capacidades LSP -## Estrategia de implementacao +- **Approach:** extrair contratos genericos em etapas, comecando pelas capacidades mais estaveis: semantic presentation/tokens, depois completion, hover e signature help. Cada etapa move um conjunto de tipos PBS-specific para modelos de frontend/language-service genericos. +- **Pro:** reduz risco, preserva o comportamento PBS existente e permite validar cada fronteira com testes focados. +- **Con:** durante a transicao o LSP pode manter alguns adapters PBS temporarios. +- **Maintainability:** forte, porque cada capacidade ganha contrato proprio e a arquitetura aprende com o codigo existente antes de generalizar tudo. -Usar `rg` para localizar termos, confirmar nomes reais, registrar classificacao no plano derivado e migrar apenas uma fronteira por vez. +### Option C - Manter LSP v1 PBS-specific por enquanto -## Testes necessarios +- **Approach:** reconhecer que PBS e o unico frontend concreto com editor assistance hoje e adiar a generalizacao ate o segundo frontend exigir LSP. +- **Pro:** custo imediato baixo e nenhum risco de abstrair prematuramente. +- **Con:** solidifica o LSP como PBS-specific e aumenta o custo da proxima linguagem; novos frontends compile-only nao terao caminho claro para capacidades editoriais. +- **Maintainability:** aceitavel no curtissimo prazo, fraca para o objetivo multi-frontend. -- Teste de dependencia impedindo imports PBS em packages comuns. -- Testes de build existentes do PBS. -- Testes de Studio/project wizard para garantir templates PBS ainda funcionam. +## Recommendation -## Criterios de aceitacao +Recomendacao fechada: seguir a **Option B - Extracao incremental por capacidades LSP**. -- Codigo comum nao decide comportamento por `"pbs"`. -- Excecoes ficam restritas a composition root, testes PBS, templates PBS e frontend PBS. +O corte deve reconhecer explicitamente que PBS continua sendo default/fallback. A decisao nao deve tentar eliminar `"pbs"` de defaults, templates ou composition root. O objetivo e remover dependencia PBS do LSP/editorial bridge onde ela impede outro frontend de implementar capacidades equivalentes. -## Riscos +Sequencia recomendada: -- Remover uma referencia valida do PBS por classificacao apressada. -- Quebrar setup de projeto existente ao mover extensoes e templates para provider. +1. classificar excecoes permitidas para referencias PBS; +2. definir um contrato generico de capacidades editoriais dentro do `FrontendProvider.languageService()` opcional, sem fragmentar o provider em varias interfaces top-level prematuras; +3. migrar semantic tokens e semantic presentation primeiro, se ainda houver acoplamento alem do spec; +4. migrar completion para modelo generico; +5. migrar hover para modelo generico, incluindo Markdown/documentation e assinatura; +6. migrar signature help para modelo generico; +7. remover o uso direto de `PbsAst`, `PbsEditorial*` e `PBSFrontendPhaseService` do LSP; +8. alimentar a agenda de testes arquiteturais (`AGD-0067`) com uma regra impedindo imports de `p.studio.compiler.pbs` no LSP comum, exceto adapters explicitamente temporarios se a decision permitir. -## Decisoes que devem ser registradas +## Discussion -- Lista de excecoes permitidas. -- Criterio de ownership para cada pacote comum. -- Ordem de migracao por area. +Esta agenda nao deve ser tratada como uma limpeza textual de `"pbs"`. +As referencias PBS se dividem em categorias diferentes: + +- **Permitidas:** frontend PBS interno, testes PBS, fixtures, templates PBS, VS Code `.pbs`, semantic keys PBS, default/fallback de criacao de projeto e bootstrap de provider enquanto PBS for o default concreto. +- **Suspeitas:** codigo comum que instancia ou chama diretamente servicos PBS quando poderia depender de `FrontendProvider`, `FrontendSpec`, capability ou contrato editorial generico. +- **Problema confirmado:** `CompilerLanguageServiceBridge` conhece tipos e servicos PBS diretamente para operar LSP/editor assistance. + +O ponto de arquitetura e que o LSP deve projetar capacidades oferecidas pelo frontend selecionado. Ele nao deve saber que o frontend selecionado e PBS para montar completion, hover, signature help ou semantic tokens. PBS deve implementar o contrato; o LSP deve consumir o contrato. + +Tambem e importante nao criar uma abstracao grande demais. Frontends podem nascer compile-only e declarar ausencia de capacidades editoriais. O contrato deve permitir capacidades opcionais, com fallback claro no LSP. + +Esta agenda deve respeitar as decisions ja consolidadas de provider: `FrontendProvider` continua sendo a unidade comum de registro, `compiler()` continua obrigatorio, `languageService()` continua opcional, e linguagens desconhecidas continuam falhando explicitamente. PBS e fallback valido apenas para ausencia de escolha/default de produto, nao para `languageId` desconhecido. + +## Resolution + +Consenso de agenda formado em favor de generalizar o contrato LSP/editorial por extracao incremental de capacidades. + +PBS permanece como linguagem default e fallback valido quando o usuario nao escolhe linguagem. Esse fallback nao se aplica a `languageId` desconhecido, que deve continuar falhando explicitamente. + +O contrato editorial generico deve ser definido em `prometeu-frontend-api`, dentro do modelo de `FrontendProvider.languageService()` opcional ja consolidado. A agenda nao reabre a decisao de provider: `compiler()` continua obrigatorio, `languageService()` continua opcional, e frontends compile-only continuam validos. + +O estado final desejado e que o LSP comum consuma modelos editoriais genericos do frontend selecionado, sem importar `p.studio.compiler.pbs.*`, sem conhecer `PbsAst.File`, e sem chamar `PBSFrontendPhaseService.semanticReadSurface(...)` diretamente. + +As capacidades devem ser migradas em etapas: + +1. semantic tokens e semantic presentation; +2. completion; +3. hover, incluindo Markdown/documentation e assinatura; +4. signature help; +5. remocao dos imports PBS do caminho comum do LSP; +6. repasse da regra de protecao para a agenda de testes arquiteturais (`AGD-0067`). + +Adapters PBS temporarios sao aceitaveis apenas durante a migracao de cada capacidade. Eles nao devem virar o contrato permanente do LSP. + +As excecoes PBS permitidas sao: + +- frontend PBS interno; +- testes PBS; +- fixtures `.pbs`; +- templates PBS; +- registro VS Code para `.pbs`; +- semantic keys PBS; +- PBS como default/fallback quando nao ha escolha explicita de linguagem; +- bootstrap/composition root enquanto PBS for o frontend concreto default. + +Referencias PBS nao permitidas no estado final: + +- LSP comum importando `p.studio.compiler.pbs.*`; +- common compiler/build/studio instanciando servicos PBS fora de provider/composition root; +- usar PBS como fallback para `languageId` desconhecido. + +## Acceptance Signals + +- PBS continua funcionando como linguagem default quando o usuario nao escolhe outra. +- Defaults, templates e fixtures PBS nao sao removidos por engano. +- O LSP deixa de importar `p.studio.compiler.pbs.*` em seu caminho comum. +- O provider/frontend language service declara capacidades editoriais de forma generica e opcional. +- PBS implementa essas capacidades sem perder completion, hover, signature help, documentation Markdown ou semantic tokens existentes. +- A agenda de testes arquiteturais cobre pelo menos um provider compile-only ou fake para provar que o LSP comum nao depende de PBS. + +## Next Step + +Fechar uma decision para: + +- declarar PBS como default/fallback permitido; +- listar excecoes permitidas para referencias PBS; +- escolher extracao incremental por capacidades LSP; +- definir os propagation targets para `prometeu-frontend-api`, `prometeu-lsp`, `prometeu-frontend-pbs` e testes arquiteturais. diff --git a/discussion/workflow/decisions/DEC-0042-frontend-editorial-language-service-contract-for-lsp.md b/discussion/workflow/decisions/DEC-0042-frontend-editorial-language-service-contract-for-lsp.md new file mode 100644 index 00000000..c8ee9c0a --- /dev/null +++ b/discussion/workflow/decisions/DEC-0042-frontend-editorial-language-service-contract-for-lsp.md @@ -0,0 +1,169 @@ +--- +id: DEC-0042 +ticket: multi-frontend-remove-pbs-branches +title: Frontend editorial language service contract for LSP +status: accepted +created: 2026-07-15 +ref_agenda: AGD-0059 +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Context + +This decision belongs to domain owner `compiler/general`. + +Touched subdomains: + +- `studio/lsp` +- `compiler/pbs` +- `compiler/frontend-api` +- `tests/architecture` + +PBS is currently the default Prometeu language and remains the only rich frontend with full editor assistance. The earlier provider work already established that shared compiler and Studio code must resolve behavior through `FrontendProvider`, where `compiler()` is mandatory and `languageService()` is optional. + +Local inspection for `AGD-0059` showed that PBS is already mostly centered in `prometeu-frontend-pbs`. The remaining architectural issue is narrower: `CompilerLanguageServiceBridge` still imports and calls PBS-specific editorial types and services directly, including `PBSFrontendLanguageService`, `PBSFrontendPhaseService`, `PbsAst`, and `PbsEditorial*` models. + +This makes the LSP path harder to reuse for another frontend. It also keeps a temporary PBS adapter shape in common LSP code after the provider boundary has already made language services optional. + +## Decision + +The common LSP/editorial path MUST consume frontend-provided editorial capabilities through a generic contract exposed from `prometeu-frontend-api`. + +`FrontendProvider` remains the common registration unit. This decision MUST NOT replace or fragment the provider contract: + +- `FrontendProvider.compiler()` MUST remain the only mandatory executable frontend capability. +- `FrontendProvider.languageService()` MUST remain optional. +- A compile-only frontend with no language service MUST remain valid. +- Unknown `languageId` values MUST continue to fail explicitly. + +The generic editorial contract MUST live behind the optional `languageService()` surface. It SHOULD be represented as an aggregated frontend language-service surface with small capability methods or capability records for: + +- semantic tokens and semantic presentation; +- completion; +- hover; +- signature help. + +Each editorial capability MUST be optional or have deterministic empty/fallback behavior. Missing editor assistance MUST NOT block analyze, compile, build, backend lowering, bytecode emission, verification, or artifact writing. + +The common LSP implementation MUST move toward consuming only generic frontend/editorial models. It MUST NOT permanently import `p.studio.compiler.pbs.*`, know `PbsAst.File`, call `PBSFrontendPhaseService.semanticReadSurface(...)`, or depend on `PbsEditorial*` models in the common path. + +PBS MUST implement or adapt to the generic editorial models from inside the PBS frontend boundary. PBS-specific types may remain internal implementation details of `prometeu-frontend-pbs`. + +Temporary PBS adapters MAY exist during migration, but only as staged compatibility while each capability is extracted. They MUST NOT be treated as the permanent LSP contract. + +PBS remains the product default language and MAY be used as the fallback when the user has not explicitly chosen a language. That default/fallback rule applies only to absence of choice. It MUST NOT be used to reinterpret an unknown `languageId` as PBS. + +The following PBS references are allowed: + +- references inside the PBS frontend implementation; +- PBS-specific tests; +- `.pbs` fixtures; +- PBS templates; +- VS Code language registration for `.pbs`; +- PBS semantic keys and visual presentation metadata; +- PBS as product default/fallback when there is no explicit language choice; +- composition-root/bootstrap registration while PBS is the concrete default frontend. + +The following PBS references are not allowed in the intended final state: + +- common LSP code importing `p.studio.compiler.pbs.*`; +- common compiler, build, Studio, or app code instantiating PBS services outside provider/composition-root ownership; +- treating unknown `languageId` as PBS. + +## Rationale + +The provider contract already separates compilation from editor assistance. Keeping `languageService()` optional protects compile-first frontends from having to implement a complete IDE experience before they can participate in the compiler pipeline. + +The remaining PBS coupling in LSP is a known temporary gap, not a desired architecture. Generalizing the LSP/editorial contract lets the selected frontend provide editor capabilities while keeping LSP as a protocol bridge instead of a PBS semantic owner. + +The decision deliberately chooses incremental extraction. A one-shot abstraction over every current PBS editorial type would be high risk because there is still only one rich frontend. Incremental capability extraction preserves PBS behavior while letting the generic contract grow from actual LSP needs. + +Keeping the contract in `prometeu-frontend-api` avoids making frontends depend on `prometeu-lsp`. It also avoids putting editor-specific DTOs into `compiler-core` unless future implementation pressure proves that they are truly compiler-core concepts. + +Allowing PBS as product default is compatible with multi-frontend architecture. Using PBS as fallback for unknown language IDs is not compatible, because it hides configuration errors and makes language identity ambiguous. + +## Implications + +- `CompilerLanguageServiceBridge` must be migrated away from PBS-specific imports in stages. +- Generic editorial DTOs must preserve the information currently needed by PBS completion, hover, signature help, documentation Markdown, and semantic tokens. +- PBS can keep rich internal models, but it must map them to generic frontend-facing models before LSP consumes them. +- Future frontends can implement only the editorial capabilities they support. +- LSP fallback behavior for missing capabilities must be explicit and deterministic. +- Architectural tests should eventually enforce that common LSP code does not import PBS implementation packages. +- PBS default project creation and composition bootstrap should not be removed merely because they mention PBS. + +## Technical Specification + +The first generic editorial model set SHOULD be small and focused on existing LSP v1 needs: + +- `FrontendCompletionCandidate` +- `FrontendHover` +- `FrontendSignatureHelp` +- `FrontendSignature` +- `FrontendSymbolKind` +- `FrontendDocumentation`, if documentation format needs to be explicit instead of plain Markdown text + +The generic model MUST represent: + +- display labels and details needed for completion; +- completion kind in language-neutral terms; +- hover Markdown or structured hover sections; +- signature labels and parameter labels; +- active signature and active parameter; +- semantic token keys already owned by `FrontendSpec`/semantic presentation; +- documentation text without requiring LSP to know PBS documentation internals. + +The migration order SHOULD be: + +1. preserve or tighten semantic tokens and semantic presentation as frontend-owned metadata; +2. migrate completion to generic frontend models; +3. migrate hover to generic frontend models, including Markdown/documentation and signatures; +4. migrate signature help to generic frontend models; +5. remove PBS imports from the common LSP path; +6. propagate import-boundary enforcement to the architectural-tests discussion. + +During migration, temporary adapter code MUST be clearly local and removable. It MUST NOT introduce a second permanent PBS-specific LSP API. + +## Constraints + +- This decision MUST NOT introduce plugin marketplace behavior, dynamic JAR loading, reflection-based discovery, RPC, sandboxing, or service locator infrastructure. +- This decision MUST NOT make language services mandatory. +- This decision MUST NOT require a second real frontend before the contract can be improved. +- This decision MUST NOT weaken PBS regression coverage for existing completion, hover, signature help, documentation Markdown, or semantic tokens. +- This decision MUST NOT move frontend semantic ownership into Studio or LSP. +- This decision MUST NOT change the rule that unknown languages fail explicitly. +- This decision MUST NOT remove PBS defaults, templates, fixtures, VS Code language registration, or composition-root bootstrap solely because they mention PBS. + +## Propagation Targets + +- specs: + - compiler/provider and frontend API specs that describe `FrontendProvider.languageService()`; + - LSP/editor-facing specs if a current Studio/LSP spec surface is active; + - architectural-boundary specs or lessons if they mention PBS import allowlists. +- plans: + - create staged plans for generic editorial DTOs and capability migration; + - coordinate the import-boundary rule with `AGD-0067`. +- code: + - `prometeu-compiler/prometeu-frontend-api`; + - `prometeu-lsp/prometeu-lsp-v1`; + - `prometeu-compiler/frontends/prometeu-frontend-pbs`; + - provider and language-service adapters as needed. +- tests: + - PBS regression tests for completion, hover, signature help, documentation Markdown, and semantic tokens; + - LSP tests for missing language-service capability fallback; + - tests with a compile-only or fake provider; + - architectural tests preventing PBS implementation imports in common LSP code after migration. +- docs: + - this discussion's future implementation plans; + - future lesson after the staged migration is complete. + +## References + +- Agenda: AGD-0059 +- Source discussion: DSC-0056 +- Related lesson: `LSN-0055` Static frontend providers before plugin architecture +- Related lesson: `LSN-0056` Compile-first frontends with optional editorial capabilities + +## Revision Log + +- 2026-07-15: Initial decision drafted from accepted `AGD-0059`. diff --git a/discussion/workflow/plans/PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md b/discussion/workflow/plans/PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md new file mode 100644 index 00000000..3ac03609 --- /dev/null +++ b/discussion/workflow/plans/PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md @@ -0,0 +1,71 @@ +--- +id: PLN-0111 +ticket: multi-frontend-remove-pbs-branches +title: Define generic frontend editorial DTOs and capability surface +status: done +created: 2026-07-15 +completed: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +`DEC-0042` requires the common LSP/editorial path to consume frontend-provided editorial capabilities through generic contracts exposed from `prometeu-frontend-api`. This plan creates the shared model surface before any LSP capability is migrated. + +## Objective + +Define the minimal generic frontend editorial API needed by LSP v1 without changing the provider contract: `FrontendProvider.compiler()` remains mandatory, `FrontendProvider.languageService()` remains optional, and compile-only frontends remain valid. + +## Dependencies + +- Requires accepted decision `DEC-0042`. +- Must complete before migrating completion, hover, signature help, or final PBS import removal. + +## Scope + +- Add generic editorial DTOs and capability methods under `prometeu-compiler/prometeu-frontend-api`. +- Keep the surface aggregated behind optional `FrontendProvider.languageService()`. +- Model empty/fallback behavior for unsupported capabilities. +- Keep frontend API independent from `prometeu-lsp`. + +## Non-Goals + +- Migrating `CompilerLanguageServiceBridge` behavior in this plan. +- Removing PBS imports from LSP in this plan. +- Adding plugin discovery, dynamic loading, RPC, sandboxing, or service locator infrastructure. +- Making `languageService()` mandatory. + +## Execution Method + +1. Inspect `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java` and current `PBSFrontendLanguageService` to identify existing method shapes. +2. Add generic models under `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services` or a nearby frontend editorial package: + - `FrontendCompletionCandidate` + - `FrontendHover` + - `FrontendSignatureHelp` + - `FrontendSignature` + - `FrontendSymbolKind` + - `FrontendDocumentation`, only if documentation format must be explicit. +3. Add or update the frontend language service interface so the optional language-service surface can expose semantic tokens, completion, hover, and signature help using generic types. +4. Define deterministic defaults for missing capabilities, such as empty completion lists, empty semantic tokens, no hover, and empty signature help. +5. Keep DTOs free of LSP4J, PBS AST, PBS semantic, and Studio UI dependencies. +6. Add API-level tests or compile fixtures proving a provider can omit `languageService()`. + +## Acceptance Criteria + +- `prometeu-frontend-api` exposes generic editorial DTOs for current LSP v1 needs. +- The API does not import `prometeu-lsp`, LSP4J, or `p.studio.compiler.pbs.*`. +- `FrontendProvider.languageService()` remains optional. +- A compile-only provider still compiles without implementing editorial methods. +- The generic model can represent labels, details, kinds, Markdown/documentation, signatures, active signature, active parameter, and semantic token keys needed by PBS. + +## Tests + +- Frontend API compile/test task. +- Existing provider boundary tests. +- Compile-only provider fixture tests proving no language service remains valid. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/...` +- `prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java` diff --git a/discussion/workflow/plans/PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md b/discussion/workflow/plans/PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md new file mode 100644 index 00000000..0d9adbb5 --- /dev/null +++ b/discussion/workflow/plans/PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md @@ -0,0 +1,98 @@ +--- +id: PLN-0112 +ticket: multi-frontend-remove-pbs-branches +title: Migrate semantic tokens to generic frontend language service +status: open +created: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +`DEC-0042` requires the LSP common path to project semantic token behavior from the selected frontend through generic frontend contracts. Semantic presentation already lives mostly in `FrontendSpec`, so this is the lowest-risk capability migration. + +## Objective + +Make LSP semantic token handling consume generic frontend language-service APIs while preserving frontend-owned semantic presentation and PBS semantic token behavior. + +## Dependencies + +- Depends on `PLN-0111` for the generic frontend editorial surface. +- Requires accepted decision `DEC-0042`. + +## Scope + +- Route semantic token requests through the provider's optional generic language service. +- Preserve `FrontendSpec.getSemanticPresentation()` as the source of token keys, host projections, themes, and default theme. +- Keep deterministic empty semantic tokens when a frontend has no language service or no semantic-token capability. + +## Non-Goals + +- Changing PBS semantic classification rules. +- Implementing semantic-token improvements from PBS-specific agendas. +- Migrating completion, hover, or signature help. +- Removing every PBS import from `CompilerLanguageServiceBridge`. + +## Execution Method + +1. Inspect `CompilerLanguageServiceBridge.semanticTokens(...)` and `PBSFrontendLanguageService.semanticTokens(...)`. +2. Add a generic semantic-token method to the frontend language-service surface if not already introduced by `PLN-0111`. +3. Adapt `PBSFrontendLanguageService` to return generic frontend semantic token records or a compatible generic token model. +4. Update `CompilerLanguageServiceBridge.semanticTokens(...)` to resolve `FrontendProvider` by `context.languageId()`, read presentation from `provider.specification()`, and call the generic semantic-token capability when present. +5. Ensure missing capability returns an empty token list with the frontend presentation legend. +6. Keep VS Code/LSP4J mapping inside `prometeu-lsp`. + +## Acceptance Criteria + +- LSP semantic token handling no longer needs PBS-specific language-service casts. +- Frontend semantic presentation remains frontend-owned. +- PBS semantic token regression tests continue to pass. +- Compile-only or no-language-service providers return deterministic empty semantic tokens. + +## Tests + +- Existing LSP semantic token tests. +- PBS frontend semantic presentation tests. +- Missing language-service fallback tests in `CompilerLanguageServiceBridgeTest`. + +## Affected Artifacts + +- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java` +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/...` +- LSP semantic-token tests. + +TBD. + +## Objective + +TBD. + +## Dependencies + +TBD. + +## Scope + +TBD. + +## Non-Goals + +TBD. + +## Execution Method + +TBD. + +## Acceptance Criteria + +TBD. + +## Tests + +TBD. + +## Affected Artifacts + +TBD. diff --git a/discussion/workflow/plans/PLN-0113-migrate-completion-to-generic-frontend-models.md b/discussion/workflow/plans/PLN-0113-migrate-completion-to-generic-frontend-models.md new file mode 100644 index 00000000..6e783948 --- /dev/null +++ b/discussion/workflow/plans/PLN-0113-migrate-completion-to-generic-frontend-models.md @@ -0,0 +1,98 @@ +--- +id: PLN-0113 +ticket: multi-frontend-remove-pbs-branches +title: Migrate completion to generic frontend models +status: open +created: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +`DEC-0042` requires completion to move from PBS-specific editorial models to generic frontend models while preserving PBS completion behavior and deterministic fallback for frontends without completion support. + +## Objective + +Migrate LSP completion handling to generic frontend completion models exposed through the selected provider's optional language service. + +## Dependencies + +- Depends on `PLN-0111`. +- Should run after `PLN-0112` so the bridge already has the provider/capability lookup pattern. + +## Scope + +- Map PBS completion candidates to generic `FrontendCompletionCandidate` values. +- Update LSP completion mapping to consume generic models. +- Preserve labels, details, kinds, origin/documentation fallback, and existing PBS behavior. + +## Non-Goals + +- Changing completion ranking or filtering. +- Expanding PBS completion depth. +- Migrating hover or signature help in this plan. +- Removing all PBS imports from LSP if hover/signature still depend on them. + +## Execution Method + +1. Inspect `PbsEditorialCompletionCandidate`, `PbsEditorialSymbolKind`, and LSP `mapCompletionItem(...)`. +2. Ensure `FrontendCompletionCandidate` can represent label, kind, detail, documentation, and origin or equivalent text. +3. Add PBS adapter code inside `PBSFrontendLanguageService` or the PBS frontend boundary to return generic completion candidates. +4. Update `CompilerLanguageServiceBridge.completion(...)` to call the generic completion capability through `FrontendProvider.languageService()`. +5. Replace PBS-specific completion-kind mapping with mapping from `FrontendSymbolKind` to `BaselineCompletionItemKind`. +6. Preserve empty completion fallback when language service or completion capability is absent. + +## Acceptance Criteria + +- LSP completion no longer consumes `PbsEditorialCompletionCandidate`. +- Completion kind mapping uses generic frontend kinds. +- Existing PBS completion tests pass without user-visible behavior changes. +- Missing capability returns a valid empty `BaselineCompletion`. + +## Tests + +- Existing PBS completion/editorial tests. +- `CompilerLanguageServiceBridgeTest` completion cases. +- Compile-only provider completion fallback test. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/...` +- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java` +- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- Completion-related tests. + +TBD. + +## Objective + +TBD. + +## Dependencies + +TBD. + +## Scope + +TBD. + +## Non-Goals + +TBD. + +## Execution Method + +TBD. + +## Acceptance Criteria + +TBD. + +## Tests + +TBD. + +## Affected Artifacts + +TBD. diff --git a/discussion/workflow/plans/PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md b/discussion/workflow/plans/PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md new file mode 100644 index 00000000..6122861d --- /dev/null +++ b/discussion/workflow/plans/PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md @@ -0,0 +1,106 @@ +--- +id: PLN-0114 +ticket: multi-frontend-remove-pbs-branches +title: Migrate hover and documentation to generic frontend models +status: open +created: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +`DEC-0042` requires hover and documentation Markdown to be represented through generic frontend models so LSP does not know PBS semantic or documentation internals. + +## Objective + +Migrate LSP hover handling to generic frontend hover models while preserving PBS signature, kind, origin, detail, and Markdown documentation behavior. + +## Dependencies + +- Depends on `PLN-0111`. +- Should run after `PLN-0113` so generic symbol kinds and documentation fields are established. + +## Scope + +- Define or finalize generic hover/documentation DTOs. +- Map `PbsEditorialResolvedSymbol` to generic hover output inside the PBS boundary. +- Update LSP hover composition to consume generic values. +- Preserve Markdown output and existing no-symbol fallback. + +## Non-Goals + +- Changing the PBS `[Doc]` language feature. +- Reformatting authored Markdown. +- Implementing go-to-definition or references. +- Migrating signature help request handling, except for shared signature DTOs used in hover. + +## Execution Method + +1. Inspect `PbsEditorialResolvedSymbol`, `PbsEditorialSignature`, and `formatHoverMarkdown(...)`. +2. Ensure generic `FrontendHover` can represent: + - display name; + - symbol kind; + - detail; + - origin; + - signatures; + - documentation Markdown. +3. Add PBS mapping from `PbsEditorialResolvedSymbol` to `FrontendHover` inside the frontend language service. +4. Update `CompilerLanguageServiceBridge.hover(...)` to call generic hover capability and format generic hover values. +5. Keep Markdown composition deterministic: signature block, kind/origin metadata, then documentation. +6. Preserve empty/no-symbol fallback when hover capability is absent. + +## Acceptance Criteria + +- LSP hover no longer consumes `PbsEditorialResolvedSymbol`. +- PBS documentation Markdown appears unchanged in hover. +- Authored Markdown is not reflowed or reparsed by LSP. +- Missing capability returns deterministic no-symbol hover behavior. + +## Tests + +- PBS hover/editorial tests. +- LSP hover mapping tests asserting Markdown payloads. +- Documentation Markdown regression tests from `DEC-0039` coverage. +- Missing hover capability fallback test. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/...` +- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java` +- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- Hover-related tests. + +TBD. + +## Objective + +TBD. + +## Dependencies + +TBD. + +## Scope + +TBD. + +## Non-Goals + +TBD. + +## Execution Method + +TBD. + +## Acceptance Criteria + +TBD. + +## Tests + +TBD. + +## Affected Artifacts + +TBD. diff --git a/discussion/workflow/plans/PLN-0115-migrate-signature-help-to-generic-frontend-models.md b/discussion/workflow/plans/PLN-0115-migrate-signature-help-to-generic-frontend-models.md new file mode 100644 index 00000000..d076fb27 --- /dev/null +++ b/discussion/workflow/plans/PLN-0115-migrate-signature-help-to-generic-frontend-models.md @@ -0,0 +1,99 @@ +--- +id: PLN-0115 +ticket: multi-frontend-remove-pbs-branches +title: Migrate signature help to generic frontend models +status: open +created: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +`DEC-0042` requires signature help to be exposed through generic frontend models rather than PBS-specific editorial models. + +## Objective + +Migrate LSP signature help handling to generic frontend signature-help models while preserving PBS callable labels, parameter labels, active signature, and active parameter behavior. + +## Dependencies + +- Depends on `PLN-0111`. +- Should run after `PLN-0114` because hover and signature help may share generic signature DTOs. + +## Scope + +- Map PBS signature help to generic `FrontendSignatureHelp` and `FrontendSignature`. +- Update LSP signature-help mapping to consume generic models. +- Preserve deterministic empty signature help when unsupported. + +## Non-Goals + +- Changing PBS callable resolution. +- Changing parameter-name semantics. +- Adding parameter documentation beyond existing behavior. +- Removing all PBS imports from LSP if other capabilities are still pending. + +## Execution Method + +1. Inspect current `PBSFrontendLanguageService.signatureHelp(...)` and `PbsEditorialSignatureHelp`. +2. Ensure generic `FrontendSignatureHelp` represents signatures, active signature, active parameter, labels, and parameter labels. +3. Add PBS mapping to generic signature help inside the PBS frontend boundary. +4. Update `CompilerLanguageServiceBridge.signatureHelp(...)` to call generic signature-help capability. +5. Preserve empty response behavior for absent language service or absent signature-help capability. +6. Verify completion/hover shared signature models still satisfy their tests. + +## Acceptance Criteria + +- LSP signature help no longer consumes PBS-specific signature-help types. +- PBS signature-help output remains stable. +- Active signature and active parameter are preserved. +- Compile-only providers receive deterministic empty signature help. + +## Tests + +- PBS signature-help/editorial tests. +- LSP signature-help bridge tests. +- Missing capability fallback tests. +- Regression tests for callable parameter labels. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/...` +- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java` +- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- Signature-help tests. + +TBD. + +## Objective + +TBD. + +## Dependencies + +TBD. + +## Scope + +TBD. + +## Non-Goals + +TBD. + +## Execution Method + +TBD. + +## Acceptance Criteria + +TBD. + +## Tests + +TBD. + +## Affected Artifacts + +TBD. diff --git a/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md b/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md new file mode 100644 index 00000000..7ddba508 --- /dev/null +++ b/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md @@ -0,0 +1,101 @@ +--- +id: PLN-0116 +ticket: multi-frontend-remove-pbs-branches +title: Remove PBS imports from common LSP and add boundary coverage +status: open +created: 2026-07-15 +ref_decisions: [DEC-0042] +tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend] +--- + +## Briefing + +After generic editorial DTOs and LSP capabilities are migrated, `DEC-0042` requires the common LSP path to stop importing PBS implementation packages and to propagate enforcement to the architectural-tests track. + +## Objective + +Remove remaining PBS implementation imports from common LSP code and add regression coverage proving LSP uses frontend/provider contracts instead of PBS internals. + +## Dependencies + +- Depends on `PLN-0111` through `PLN-0115`. +- Coordinates with `AGD-0067` for broader architectural-test policy. + +## Scope + +- Remove `p.studio.compiler.pbs.*` imports from the common `CompilerLanguageServiceBridge` path. +- Remove direct use of `PbsAst.File`, `PbsEditorial*`, and `PBSFrontendPhaseService.semanticReadSurface(...)` from common LSP code. +- Add local boundary tests or feed the final rule into the architectural-tests discussion. +- Preserve PBS default/fallback behavior for no explicit language choice. + +## Non-Goals + +- Removing PBS from composition root, templates, fixtures, VS Code `.pbs` registration, semantic keys, or PBS frontend internals. +- Changing unknown `languageId` failure behavior. +- Introducing ArchUnit unless `AGD-0067` chooses it. +- Implementing new LSP features. + +## Execution Method + +1. Search `prometeu-lsp/prometeu-lsp-v1/src/main/java` for `p.studio.compiler.pbs`, `PbsAst`, `PbsEditorial`, and `PBSFrontendPhaseService`. +2. Replace remaining common-path dependencies with generic frontend language-service calls. +3. If any PBS adapter remains, move it behind an explicitly local adapter boundary and document why it is temporary. +4. Add or update tests using a compile-only or fake provider to prove semantic tokens, completion, hover, and signature help do not require PBS. +5. Add a simple import-boundary test if one can be implemented without new infrastructure; otherwise update `AGD-0067`/derived plan with the exact rule. +6. Run relevant LSP and PBS regression tests. + +## Acceptance Criteria + +- Common LSP production code does not import `p.studio.compiler.pbs.*`. +- Common LSP production code does not know `PbsAst.File`, `PbsEditorial*`, or `PBSFrontendPhaseService`. +- Unknown `languageId` still fails explicitly. +- PBS remains product default/fallback when no language is chosen. +- Tests prove missing language-service capabilities produce deterministic fallback responses. +- Architectural-test follow-up is recorded for any repository-wide import rule not implemented locally. + +## Tests + +- `prometeu-lsp` tests. +- PBS frontend editorial regression tests. +- Provider boundary tests with compile-only/fake providers. +- Import-boundary test for common LSP code if feasible. + +## Affected Artifacts + +- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- `prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java` +- Architectural-test discussion or future plan from `AGD-0067` + +TBD. + +## Objective + +TBD. + +## Dependencies + +TBD. + +## Scope + +TBD. + +## Non-Goals + +TBD. + +## Execution Method + +TBD. + +## Acceptance Criteria + +TBD. + +## Tests + +TBD. + +## Affected Artifacts + +TBD. diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendCompletionCandidate.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendCompletionCandidate.java new file mode 100644 index 00000000..221a3764 --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendCompletionCandidate.java @@ -0,0 +1,33 @@ +package p.studio.compiler.services; + +import java.util.Objects; + +public record FrontendCompletionCandidate( + String label, + FrontendSymbolKind kind, + String detail, + String documentation, + String origin) { + + public FrontendCompletionCandidate { + label = requireText(label, "label"); + kind = Objects.requireNonNull(kind, "kind"); + detail = normalize(detail); + documentation = normalize(documentation); + origin = normalize(origin); + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentRequest.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentRequest.java new file mode 100644 index 00000000..5c3b20d5 --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentRequest.java @@ -0,0 +1,22 @@ +package p.studio.compiler.services; + +import java.nio.file.Path; +import java.util.Objects; + +public record FrontendDocumentRequest( + Path projectRoot, + Path documentPath, + String documentText) { + + public FrontendDocumentRequest { + projectRoot = normalizePath(projectRoot, "projectRoot"); + documentPath = normalizePath(documentPath, "documentPath"); + documentText = documentText == null ? "" : documentText; + } + + private static Path normalizePath( + final Path path, + final String field) { + return Objects.requireNonNull(path, field).toAbsolutePath().normalize(); + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentation.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentation.java new file mode 100644 index 00000000..af21850f --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentation.java @@ -0,0 +1,21 @@ +package p.studio.compiler.services; + +import java.util.Objects; + +public record FrontendDocumentation( + FrontendDocumentationFormat format, + String text) { + + public FrontendDocumentation { + format = Objects.requireNonNull(format, "format"); + text = text == null ? "" : text; + } + + public boolean isBlank() { + return text.isBlank(); + } + + public static FrontendDocumentation markdown(final String text) { + return new FrontendDocumentation(FrontendDocumentationFormat.MARKDOWN, text); + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentationFormat.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentationFormat.java new file mode 100644 index 00000000..ffb13aac --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendDocumentationFormat.java @@ -0,0 +1,6 @@ +package p.studio.compiler.services; + +public enum FrontendDocumentationFormat { + MARKDOWN, + PLAINTEXT +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendHover.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendHover.java new file mode 100644 index 00000000..071526ff --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendHover.java @@ -0,0 +1,38 @@ +package p.studio.compiler.services; + +import java.util.List; +import java.util.Objects; + +public record FrontendHover( + String displayName, + FrontendSymbolKind kind, + String detail, + String origin, + List signatures, + FrontendDocumentation documentation) { + + public FrontendHover { + displayName = requireText(displayName, "displayName"); + kind = Objects.requireNonNull(kind, "kind"); + detail = normalize(detail); + origin = normalize(origin); + signatures = signatures == null ? List.of() : List.copyOf(signatures); + documentation = documentation == null + ? FrontendDocumentation.markdown("") + : documentation; + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java index 529d8cac..51190bd6 100644 --- a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java @@ -1,7 +1,33 @@ package p.studio.compiler.services; +import p.studio.compiler.models.FrontendSemanticToken; + +import java.util.List; +import java.util.Optional; + /** - * Marker contract for optional frontend-owned editor services. + * Optional frontend-owned editor services. */ public interface FrontendLanguageService { + default List semanticTokens(final FrontendDocumentRequest request) { + return List.of(); + } + + default List completion( + final FrontendDocumentRequest request, + final int offset) { + return List.of(); + } + + default Optional hover( + final FrontendDocumentRequest request, + final int offset) { + return Optional.empty(); + } + + default FrontendSignatureHelp signatureHelp( + final FrontendDocumentRequest request, + final int offset) { + return FrontendSignatureHelp.empty(); + } } diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignature.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignature.java new file mode 100644 index 00000000..40dfc86f --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignature.java @@ -0,0 +1,28 @@ +package p.studio.compiler.services; + +import java.util.List; +import java.util.Objects; + +public record FrontendSignature( + String label, + List parameterLabels, + String documentation) { + + public FrontendSignature { + label = requireText(label, "label"); + parameterLabels = parameterLabels == null ? List.of() : parameterLabels.stream() + .map(parameterLabel -> requireText(parameterLabel, "parameterLabel")) + .toList(); + documentation = documentation == null ? "" : documentation.trim(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignatureHelp.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignatureHelp.java new file mode 100644 index 00000000..b052eb95 --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSignatureHelp.java @@ -0,0 +1,23 @@ +package p.studio.compiler.services; + +import java.util.List; + +public record FrontendSignatureHelp( + List signatures, + int activeSignature, + int activeParameter) { + + public FrontendSignatureHelp { + signatures = signatures == null ? List.of() : List.copyOf(signatures); + if (activeSignature < 0) { + throw new IllegalArgumentException("activeSignature must be >= 0"); + } + if (activeParameter < 0) { + throw new IllegalArgumentException("activeParameter must be >= 0"); + } + } + + public static FrontendSignatureHelp empty() { + return new FrontendSignatureHelp(List.of(), 0, 0); + } +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSymbolKind.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSymbolKind.java new file mode 100644 index 00000000..cfec8cda --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendSymbolKind.java @@ -0,0 +1,21 @@ +package p.studio.compiler.services; + +public enum FrontendSymbolKind { + KEYWORD, + LOCAL, + PARAMETER, + FIELD, + FUNCTION, + METHOD, + CONSTRUCTOR, + STRUCT, + BUILTIN_TYPE, + SERVICE, + HOST, + CONTRACT, + CALLBACK, + ENUM, + ERROR, + GLOBAL, + CONST +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/services/FrontendLanguageServiceTest.java b/prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/services/FrontendLanguageServiceTest.java new file mode 100644 index 00000000..25c3dc25 --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/services/FrontendLanguageServiceTest.java @@ -0,0 +1,63 @@ +package p.studio.compiler.services; + +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class FrontendLanguageServiceTest { + + @Test + void defaultLanguageServiceCapabilitiesAreEmpty() { + final FrontendLanguageService service = new FrontendLanguageService() { + }; + final FrontendDocumentRequest request = new FrontendDocumentRequest( + Path.of("."), + Path.of("src/main.pbs"), + "fun main() {}"); + + assertTrue(service.semanticTokens(request).isEmpty()); + assertTrue(service.completion(request, 0).isEmpty()); + assertTrue(service.hover(request, 0).isEmpty()); + assertEquals(FrontendSignatureHelp.empty(), service.signatureHelp(request, 0)); + } + + @Test + void completionCandidateNormalizesOptionalText() { + final var candidate = new FrontendCompletionCandidate( + " draw ", + FrontendSymbolKind.FUNCTION, + " callable ", + " docs ", + " stdlib "); + + assertEquals("draw", candidate.label()); + assertEquals("callable", candidate.detail()); + assertEquals("docs", candidate.documentation()); + assertEquals("stdlib", candidate.origin()); + } + + @Test + void hoverDefaultsToEmptyMarkdownDocumentation() { + final var hover = new FrontendHover( + "draw", + FrontendSymbolKind.FUNCTION, + null, + null, + List.of(new FrontendSignature("draw(x)", List.of("x"), null)), + null); + + assertEquals("draw", hover.displayName()); + assertTrue(hover.documentation().isBlank()); + assertEquals(FrontendDocumentationFormat.MARKDOWN, hover.documentation().format()); + assertEquals(1, hover.signatures().size()); + } + + @Test + void signatureHelpRejectsNegativeActiveIndexes() { + assertThrows(IllegalArgumentException.class, () -> new FrontendSignatureHelp(List.of(), -1, 0)); + assertThrows(IllegalArgumentException.class, () -> new FrontendSignatureHelp(List.of(), 0, -1)); + } +}