From 6cd24bf14ff24e6d85826dc62d45caef495b09a2 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 09:40:13 +0100 Subject: [PATCH 1/5] implements PLN-0107 --- discussion/index.ndjson | 4 +- ...-frontend-compiler-vs-language-services.md | 2 +- ...lation-from-editorial-language-services.md | 104 ++++++++++++++++++ ...piler-and-editorial-capability-boundary.md | 68 ++++++++++++ ...stance-behind-optional-language-service.md | 71 ++++++++++++ ...ke-lsp-editorial-calls-capability-aware.md | 74 +++++++++++++ ...-absent-capability-conformance-coverage.md | 72 ++++++++++++ ...ler Pipeline Entry Points Specification.md | 32 +++++- 8 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md create mode 100644 discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md create mode 100644 discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md create mode 100644 discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md create mode 100644 discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 731aace8..8a1e3fcc 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":41,"PLN":107,"LSN":56,"CLSN":1}} +{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":42,"PLN":111,"LSN":56,"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":[]} @@ -9,7 +9,7 @@ {"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-0055","status":"open","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0052","status":"open","ticket":"pbs-lsp-document-links","title":"PBS LSP Document Links","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","document-links","imports"],"agendas":[{"id":"AGD-0055","file":"AGD-0055-pbs-lsp-document-links.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md b/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md index 8ee45c2e..6639083e 100644 --- a/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md +++ b/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md @@ -2,7 +2,7 @@ id: AGD-0058 ticket: multi-frontend-compiler-vs-language-services title: Separar compilacao de servicos editoriais de frontend -status: open +status: accepted created: 2026-07-15 resolved: decision: diff --git a/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md b/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md new file mode 100644 index 00000000..96d0adea --- /dev/null +++ b/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md @@ -0,0 +1,104 @@ +--- +id: DEC-0041 +ticket: multi-frontend-compiler-vs-language-services +title: Separate frontend compilation from editorial language services +status: accepted +created: 2026-07-15 +ref_agenda: AGD-0058 +tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] +--- + +## Context + +Prometeu is preparing the compiler and editor stack for multiple frontends. PBS currently provides compilation and rich editor assistance, and existing LSP/Studio paths can still assume that diagnostics, semantic tokens, completion, hover, and signature help are all backed by the PBS frontend implementation. + +This decision belongs to domain owner `compiler/general`. + +Touched subdomains: + +- `studio/lsp` +- `compiler/pbs` + +The existing API already points in the right direction: `FrontendProvider` exposes mandatory compiler behavior through `compiler()` and optional editor behavior through `languageService()`. However, the LSP bridge still contains PBS-specific editorial logic, so the boundary needs to be made normative before implementation plans migrate consumers. + +This decision resolves `AGD-0058`. + +## Decision + +Frontend compilation and editorial language services MUST be separate contracts. + +Every frontend MUST provide a compiler contract. A frontend MAY provide editorial language services. A frontend that can compile but does not provide completion, hover, definition, signature help, semantic tokens, or other editor assistance MUST still be considered a valid frontend. + +`FrontendProvider.compiler()` is the required frontend capability. It MUST remain sufficient for build, analyze, compile, and backend-facing pipeline flows. + +`FrontendProvider.languageService()` is the optional editorial capability boundary. The absence of a language service MUST NOT prevent compilation, project analysis, or backend execution. + +The first common editorial contract SHOULD remain aggregated as `FrontendLanguageService` plus explicit capabilities, rather than immediately splitting every feature into separate top-level service interfaces. Smaller feature interfaces MAY be introduced later when implementation pressure proves that independent ownership, testing, or lifecycle is needed. + +LSP and Studio consumers MUST query editorial capability availability before invoking editor-specific behavior. They MUST NOT assume that a frontend with a compiler also supports completion, hover, definition, semantic tokens, signature help, formatting, rename, code actions, or similar editor features. + +When an editorial capability is absent, LSP and Studio MUST degrade gracefully: + +- collection-shaped responses SHOULD be empty; +- scalar optional responses SHOULD be absent or use a documented neutral response; +- protocol-level unsupported behavior SHOULD be explicit when the host protocol supports that distinction; +- absence MUST NOT be reported as a compiler failure. + +PBS MAY continue to expose the rich editorial behavior it has today. That behavior is a PBS-provided capability, not a requirement imposed on all future frontends. + +Compiler diagnostics and editorial diagnostics MUST remain distinct concepts. Build/analyze diagnostics belong to the compiler contract. Editorial diagnostics MAY reuse compiler analysis results, but a frontend MUST NOT be required to provide a separate editor diagnostics service in order to compile. + +Semantic presentation metadata, such as frontend-owned semantic token vocabularies and visual themes, remains frontend-owned presentation data. Producing semantic tokens for a live document is an editorial capability and MUST be optional unless a future decision narrows that requirement for a specific host. + +The LSP implementation SHOULD migrate from direct PBS editorial calls toward resolving the active frontend provider and consulting its optional language-service capabilities. Until that migration is planned and implemented, PBS-specific bridge code is tolerated as legacy coupling, not as the normative architecture. + +## Rationale + +Multi-frontend support requires a low floor: a new language frontend should be able to join the build pipeline before it has IDE-grade assistance. Requiring all editor features up front would turn frontend adoption into a large all-or-nothing task and would couple compiler correctness to UX completeness. + +Keeping the first editorial boundary aggregated avoids premature interface explosion. The codebase already has a marker `FrontendLanguageService`, while the real uncertainty is how LSP/Studio should discover and handle absent capabilities. Capability negotiation solves that problem without forcing a final taxonomy before there is enough implementation evidence. + +Separating compiler diagnostics from editorial diagnostics protects latency and ownership boundaries. Build diagnostics can be produced as part of normal analysis, while editor diagnostics may need live overlays, partial results, cancellation, caching, or host-specific behavior. + +PBS should remain the reference rich frontend, but it should not define the minimum contract for all future languages. Treating PBS editor support as optional capability data makes the current implementation useful without freezing PBS assumptions into the common compiler API. + +## Implications + +- Common compiler code MUST depend on the compiler capability, not on PBS-specific frontend services. +- LSP/Studio code that invokes editor behavior MUST handle absent capabilities deterministically. +- Existing PBS editor assistance should be preserved while being moved behind the common optional language-service boundary over time. +- Future frontend tests should include at least one compile-capable frontend with no language service. +- Future LSP/Studio tests should prove that absent capabilities produce empty or unsupported responses rather than build failures. +- Introducing smaller editorial interfaces is allowed later, but only after a plan identifies real feature lifecycle boundaries. +- Plans derived from this decision MUST NOT reinterpret optional editorial services as required for frontend validity. + +## Propagation Targets + +- specs: + - `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` + - A future compiler/frontend provider contract spec if one is created. + - LSP/editor-facing specs if/when a dedicated Studio/LSP spec surface exists. +- plans: + - Create a plan to specify the frontend provider/editorial capability boundary. + - Create a plan to migrate LSP/Studio consumers away from direct PBS editorial assumptions. +- code: + - `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java` + - `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` + - `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` + - PBS frontend editorial support classes. +- tests: + - Frontend provider tests proving compilation works without a language service. + - LSP/Studio tests for absent completion, hover, signature help, semantic tokens, and future editorial capabilities. + - Regression tests proving PBS still exposes current editorial behavior. +- docs: + - Specs updated by implementation plans. + - Lessons generated after implementation and housekeeping. + +## References + +- Agenda: AGD-0058 +- Source discussion: DSC-0055 + +## Revision Log + +- 2026-07-15: Initial decision drafted from accepted `AGD-0058`. diff --git a/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md b/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md new file mode 100644 index 00000000..0c4d1d05 --- /dev/null +++ b/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md @@ -0,0 +1,68 @@ +--- +id: PLN-0107 +ticket: multi-frontend-compiler-vs-language-services +title: Specify frontend compiler and editorial capability boundary +status: done +created: 2026-07-15 +ref_decisions: [DEC-0041] +tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] +--- + +## Briefing + +`DEC-0041` makes compilation mandatory and editorial language services optional for every frontend. This plan updates the normative compiler-facing documentation so future implementation work has a precise boundary to follow. + +## Objective + +Document the frontend provider contract: compiler capability is required, editorial capabilities are optional, and absent editorial support must not invalidate build, analyze, compile, or backend flows. + +## Dependencies + +- Accepted decision: `DEC-0041`. +- Existing `FrontendProvider.compiler()` and `FrontendProvider.languageService()` API shape. +- Existing compiler pipeline entrypoint specification. + +## Scope + +- Update compiler specs to state that `FrontendProvider.compiler()` is the required frontend capability. +- Define `FrontendProvider.languageService()` as the optional editorial capability boundary. +- Document expected fallback behavior for absent editorial capabilities at the compiler/LSP boundary. +- Document that build/analyze diagnostics are compiler diagnostics, while editor diagnostics are optional editorial behavior. +- Add a short capability vocabulary for completion, hover, definition, signature help, semantic tokens, formatting, rename, and code actions without requiring all of them to exist now. + +## Non-Goals + +- Implement Java API changes. +- Migrate PBS editor assistance. +- Change LSP behavior. +- Split `FrontendLanguageService` into many top-level interfaces. +- Choose a plugin or process model for external frontends. + +## Execution Method + +1. Update `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` with a subsection for frontend provider capability boundaries. +2. State that compiler entrypoints must depend on the compiler capability only and must not require editorial services. +3. Define optional editorial capabilities as host-facing editor assistance, not backend-facing compilation requirements. +4. Record fallback semantics: absent collection-shaped editorial results are empty, absent scalar results are neutral/absent, and protocol unsupported states are explicit where available. +5. Document diagnostics ownership: build/analyze diagnostics are compiler contract output; editor diagnostics may reuse compiler analysis but are not required for frontend validity. +6. Add cross-references to `DEC-0041` and existing frontend provider docs or lessons where appropriate. + +## Acceptance Criteria + +- The compiler spec explicitly separates required compiler capability from optional editorial capability. +- The spec states that compile-capable frontends with no language service are valid. +- The spec states that absent editorial capability is not a compiler failure. +- The spec does not require JSON, RPC, plugin loading, out-of-process frontends, or a wire format. +- The spec keeps `FrontendLanguageService` aggregated for now and does not mandate premature feature-interface splitting. + +## Tests + +- Documentation-only plan: run `discussion validate` after updates. +- If markdown/spec linting exists locally, run the relevant docs validation task. +- Future implementation tests are delegated to `PLN-0110`. + +## Affected Artifacts + +- `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` +- `discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md` +- This plan. diff --git a/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md b/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md new file mode 100644 index 00000000..fed06a1c --- /dev/null +++ b/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md @@ -0,0 +1,71 @@ +--- +id: PLN-0108 +ticket: multi-frontend-compiler-vs-language-services +title: Move PBS editor assistance behind optional language service +status: open +created: 2026-07-15 +ref_decisions: [DEC-0041] +tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] +--- + +## Briefing + +`DEC-0041` allows PBS to keep rich editor assistance, but that behavior must become a PBS-provided optional capability instead of a common frontend requirement. This plan moves PBS completion, hover, signature help, semantic token production, and related editorial behavior behind the optional language-service boundary. + +## Objective + +Expose PBS editor assistance through `FrontendProvider.languageService()` while preserving current PBS behavior and keeping `FrontendProvider.compiler()` sufficient for compilation. + +## Dependencies + +- Accepted decision: `DEC-0041`. +- `PLN-0107` should define the documented boundary before final implementation review. +- Existing PBS editorial support classes and LSP bridge behavior. + +## Scope + +- Introduce or extend PBS language-service implementation under the PBS frontend module. +- Make `PBSFrontendProvider.languageService()` return a PBS language service. +- Keep `PBSFrontendProvider.compiler()` unchanged as the required compiler path. +- Move PBS-specific editorial calls into the PBS language-service implementation or adapter. +- Preserve existing completion, hover, signature help, semantic token, and documentation behavior for PBS. + +## Non-Goals + +- Change PBS language semantics. +- Add new editor features. +- Rewrite the LSP protocol layer. +- Implement capability-aware LSP fallbacks; that belongs to `PLN-0109`. +- Split every editor feature into independent top-level service interfaces unless strictly required by local implementation shape. + +## Execution Method + +1. Inspect `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` and define the minimum capability accessors needed by current PBS editor behavior. +2. Add a PBS language-service implementation in the PBS frontend module, colocated with existing PBS editorial support classes. +3. Move or delegate completion, hover, signature help, and semantic token behavior from PBS-specific bridge code into the PBS language-service implementation without changing output models unless the boundary requires neutral compiler-facing DTOs. +4. Update `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java` to return `Optional.of(pbsLanguageService)`. +5. Keep compile/analyze/build paths independent of `languageService()`. +6. Preserve current PBS editorial tests by redirecting setup to the new PBS language-service surface where appropriate. + +## Acceptance Criteria + +- PBS provider exposes a non-empty optional language service. +- PBS compilation still works when only `compiler()` is used. +- PBS completion, hover, signature help, semantic tokens, and documentation behavior remain equivalent to current behavior. +- Common compiler modules do not instantiate PBS editorial implementation directly. +- No new requirement is introduced for non-PBS frontends to implement editor assistance. + +## Tests + +- Run PBS frontend tests covering editorial support. +- Run LSP tests that currently assert PBS completion, hover, signature help, semantic tokens, and documentation behavior. +- Add or update provider tests proving PBS has a language service while a compile-only provider can omit it. +- Run targeted Gradle tasks for changed compiler frontend and LSP modules. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` +- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java` +- PBS editorial support classes under `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java` +- Related PBS frontend tests. +- Related LSP bridge tests. diff --git a/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md b/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md new file mode 100644 index 00000000..ea7bcf36 --- /dev/null +++ b/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md @@ -0,0 +1,74 @@ +--- +id: PLN-0109 +ticket: multi-frontend-compiler-vs-language-services +title: Make LSP editorial calls capability aware +status: open +created: 2026-07-15 +ref_decisions: [DEC-0041] +tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] +--- + +## Briefing + +`DEC-0041` requires LSP and Studio consumers to query editorial capability availability before invoking editor-specific behavior. The current LSP bridge still contains PBS-specific editorial logic. This plan migrates LSP editorial calls to capability-aware provider lookup and graceful fallbacks. + +## Objective + +Make LSP completion, hover, signature help, semantic tokens, and future editorial calls resolve the active frontend provider, consult optional language-service capabilities, and return deterministic neutral responses when capabilities are absent. + +## Dependencies + +- Accepted decision: `DEC-0041`. +- `PLN-0108` should expose PBS editor assistance through `FrontendProvider.languageService()`. +- Existing `FrontendRegistryService` frontend lookup. +- Existing LSP baseline messages and tests. + +## Scope + +- Update LSP bridge code to resolve frontend providers rather than hard-coding PBS editorial paths. +- Add fallback behavior for absent completion, hover, signature help, and semantic token capability. +- Preserve compiler-backed diagnostics through analyze/build paths. +- Keep PBS editorial behavior stable when its language service is present. +- Document or encode unsupported/neutral responses according to existing LSP baseline message shapes. + +## Non-Goals + +- Add new LSP features. +- Change VSCode extension behavior beyond consuming existing baseline responses. +- Remove all PBS-specific code in one step if adapter compatibility still requires local mapping. +- Make semantic presentation metadata optional; only live semantic token production is optional. + +## Execution Method + +1. Inspect `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` and identify all direct PBS editorial calls. +2. Add a provider-resolution path using `FrontendRegistryService` or the existing registry abstraction for `context.languageId()`. +3. For each editorial endpoint, query `provider.languageService()` and then the relevant capability before invoking implementation behavior. +4. Return neutral fallbacks when absent: + - completion: incomplete `false` with empty items; + - hover: absent/neutral hover content according to current baseline message constraints; + - signature help: empty signatures with stable active indices; + - semantic tokens: frontend legend/presentation where available and empty token list when live tokenization is absent. +5. Keep `analyzeDocument` compiler-diagnostic behavior on the compiler pipeline and do not require `languageService()`. +6. Update tests to cover both PBS-present and capability-absent frontends. + +## Acceptance Criteria + +- LSP editorial endpoints do not assume every compiler frontend has editor assistance. +- Absent editorial capabilities produce deterministic empty or neutral responses, not compiler failures. +- Compiler diagnostics still work without a language service. +- PBS editor assistance remains unchanged when PBS language service is available. +- Any remaining PBS-specific code is adapter-local and documented as temporary if not removed. + +## Tests + +- Add LSP tests for a compile-only frontend or stub provider with no language service. +- Preserve existing `CompilerLanguageServiceBridgeTest` coverage for PBS completion, hover, signature help, and semantic tokens. +- Add regression coverage that `analyzeDocument` returns compiler diagnostics independently of editorial services. +- Run targeted LSP module tests. + +## 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` +- LSP baseline message types only if neutral response representation is currently insufficient. +- Frontend registry integration points used by LSP. diff --git a/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md b/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md new file mode 100644 index 00000000..b0257383 --- /dev/null +++ b/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md @@ -0,0 +1,72 @@ +--- +id: PLN-0110 +ticket: multi-frontend-compiler-vs-language-services +title: Add compile only frontend and absent capability conformance coverage +status: open +created: 2026-07-15 +ref_decisions: [DEC-0041] +tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] +--- + +## Briefing + +`DEC-0041` requires proof that a frontend can compile without editor assistance and that LSP/Studio behavior remains deterministic when editorial capabilities are absent. This plan adds focused conformance coverage so future changes cannot accidentally make language services mandatory again. + +## Objective + +Add tests and lightweight fixtures proving compile-only frontends are valid, compiler diagnostics remain available, and absent editorial capabilities produce graceful fallback responses. + +## Dependencies + +- Accepted decision: `DEC-0041`. +- `PLN-0107` for documented contract language. +- `PLN-0109` for capability-aware LSP behavior before all fallback tests can pass. + +## Scope + +- Add a compile-only test frontend/provider fixture that implements compiler behavior and omits `languageService()`. +- Add provider boundary tests proving build/analyze/compile flows do not require editor services. +- Add LSP fallback tests for absent completion, hover, signature help, semantic tokens, and future editorial capability slots when present in the API. +- Add PBS regression tests proving rich PBS editor behavior remains available. +- Add architecture tests that prevent common compiler modules from depending on PBS-specific editor services. + +## Non-Goals + +- Build a production non-PBS frontend. +- Add a plugin loader. +- Add new editor features. +- Replace all PBS tests with generic frontend tests. +- Test external process or wire-format behavior. + +## Execution Method + +1. Locate existing provider and boundary tests, including `FrontendProviderBoundaryTest`. +2. Add a compile-only provider fixture in the narrowest test source set that can exercise the provider contract without production registration churn. +3. Write compiler-side tests asserting the fixture has a compiler, has no language service, and can participate in the relevant build/analyze/compile path selected for the fixture. +4. Add LSP tests using the compile-only or stub frontend path to assert neutral responses for absent editorial capabilities. +5. Preserve or extend PBS regression tests to show PBS still exposes completion, hover, signature help, semantic tokens, and documentation. +6. Add architecture assertions that common compiler/pipeline modules do not instantiate PBS editorial services directly. + +## Acceptance Criteria + +- At least one test frontend is compile-capable with `languageService()` empty. +- Compiler/pipeline tests prove editor services are not required for compilation or analysis. +- LSP tests prove absent editorial capabilities are handled without exceptions or compiler failures. +- PBS tests prove existing editorial behavior is still available. +- Tests do not depend on JSON, RPC, plugin loading, external processes, or future wire formats. + +## Tests + +- Run compiler frontend API/provider tests. +- Run build pipeline boundary tests. +- Run targeted LSP tests. +- Run any architecture/reflection tests added for the no-PBS-editorial-dependency rule. +- Run `discussion validate` after plan status or workflow updates. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java` +- Relevant frontend provider tests under `prometeu-compiler`. +- Relevant LSP tests under `prometeu-lsp/prometeu-lsp-v1/src/test/java` +- Test fixtures for a compile-only frontend/provider. +- This plan and linked workflow metadata. diff --git a/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md b/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md index a63c4e0d..168f3b1c 100644 --- a/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md +++ b/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md @@ -241,7 +241,37 @@ At minimum, each provider MUST expose: 2. `compiler()`, returning the compiler-facing frontend service used by the shared build pipeline; 3. `languageService()`, returning an optional editor-facing language-service capability for tooling consumers. -`languageService()` MUST be optional. A frontend that supports compilation but does not provide editor services MUST remain a valid provider. +`compiler()` is the only required executable frontend capability. It MUST be sufficient for `analyze`, `compile`, `build`, and backend-facing pipeline flows. + +`languageService()` MUST be optional. A frontend that supports compilation but does not provide editor services MUST remain a valid provider. Absence of `languageService()` MUST NOT prevent project analysis, compilation, backend lowering, bytecode emission, verification, or artifact writing. + +The first shared editor-facing contract SHOULD remain an aggregated language-service capability surface. The common compiler contract MUST NOT require separate top-level service interfaces for each editor feature until a future accepted decision and plan identify a real lifecycle, ownership, or testing boundary that requires that split. + +When exposed, editor-facing capabilities MAY include: + +1. diagnostics intended for live editor sessions, +2. completion, +3. hover, +4. definition and navigation, +5. signature help, +6. semantic tokens for a live document, +7. formatting, +8. rename, +9. code actions, +10. and other host-facing editor assistance. + +These capabilities are optional unless a future frontend- or host-specific decision makes one of them mandatory for a narrower surface. Tooling consumers MUST query capability availability before invoking editor-specific behavior. + +Absent editor capabilities MUST have deterministic fallback behavior at tooling boundaries: + +1. collection-shaped responses SHOULD be empty; +2. scalar optional responses SHOULD be absent or use a documented neutral response; +3. host protocols that can represent unsupported operations SHOULD do so explicitly; +4. and absent editor capability MUST NOT be reported as a compiler failure. + +Compiler diagnostics and editor diagnostics are distinct ownership surfaces. Diagnostics returned by `analyze`, `compile`, and `build` are compiler contract output. Editor diagnostics MAY reuse compiler analysis results, live overlays, caches, or cancellation-aware tooling state, but a frontend MUST NOT be required to provide editor diagnostics in order to compile. + +`FrontendSpec` remains the source of static frontend-owned presentation metadata such as semantic vocabularies, host projections, and visual themes. Producing semantic tokens for a live document is an optional editor-facing capability; the existence of static presentation metadata MUST NOT imply that every frontend can provide live semantic-token results. The frontend registry MUST resolve providers by `languageId`. A lookup for an unknown `languageId` MUST fail explicitly with a diagnostic-friendly error. Unknown languages MUST NOT silently fall back to PBS or to any other frontend. -- 2.47.2 From bc95b33bd98d38cb4df35ce1a926a2fb5d51dde9 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 09:41:54 +0100 Subject: [PATCH 2/5] implements PLN-0108 --- discussion/index.ndjson | 2 +- ...stance-behind-optional-language-service.md | 2 +- .../compiler/PBSFrontendLanguageService.java | 62 +++++++++++++++++++ .../studio/compiler/PBSFrontendProvider.java | 18 +++++- .../compiler/PBSFrontendProviderTest.java | 5 +- 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 8a1e3fcc..9bbf5c5d 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -9,7 +9,7 @@ {"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-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0052","status":"open","ticket":"pbs-lsp-document-links","title":"PBS LSP Document Links","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","document-links","imports"],"agendas":[{"id":"AGD-0055","file":"AGD-0055-pbs-lsp-document-links.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md b/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md index fed06a1c..de41ce38 100644 --- a/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md +++ b/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md @@ -2,7 +2,7 @@ id: PLN-0108 ticket: multi-frontend-compiler-vs-language-services title: Move PBS editor assistance behind optional language service -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0041] tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java new file mode 100644 index 00000000..e56ceadd --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java @@ -0,0 +1,62 @@ +package p.studio.compiler; + +import p.studio.compiler.messages.FESurfaceContext; +import p.studio.compiler.models.FrontendSemanticToken; +import p.studio.compiler.pbs.ast.PbsAst; +import p.studio.compiler.pbs.semantics.PbsEditorialCompletionCandidate; +import p.studio.compiler.pbs.semantics.PbsEditorialResolvedSymbol; +import p.studio.compiler.pbs.semantics.PbsEditorialSignatureHelp; +import p.studio.compiler.pbs.semantics.PbsEditorialSupportService; +import p.studio.compiler.services.FrontendLanguageService; +import p.studio.utilities.structures.ReadOnlyList; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +public final class PBSFrontendLanguageService implements FrontendLanguageService { + private final PbsEditorialSupportService editorialSupportService; + private final PBSSemanticTokenProvider semanticTokenProvider; + + public PBSFrontendLanguageService() { + this(new PbsEditorialSupportService(), new PBSSemanticTokenProvider()); + } + + PBSFrontendLanguageService( + final PbsEditorialSupportService editorialSupportService, + final PBSSemanticTokenProvider semanticTokenProvider) { + this.editorialSupportService = Objects.requireNonNull(editorialSupportService, "editorialSupportService"); + this.semanticTokenProvider = Objects.requireNonNull(semanticTokenProvider, "semanticTokenProvider"); + } + + public List completion( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + return editorialSupportService.completion(sourceText, ast, supplementalTopDecls, feSurfaceContext, offset); + } + + public Optional hover( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + return editorialSupportService.hover(sourceText, ast, supplementalTopDecls, feSurfaceContext, offset); + } + + public Optional signatureHelp( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + return editorialSupportService.signatureHelp(sourceText, ast, supplementalTopDecls, feSurfaceContext, offset); + } + + public List semanticTokens(final String documentText) { + return semanticTokenProvider.tokenize(documentText == null ? "" : documentText); + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java index db1a2c94..a411072a 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java @@ -1,19 +1,30 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSpec; +import p.studio.compiler.services.FrontendLanguageService; import p.studio.compiler.services.FrontendPhaseService; import p.studio.compiler.services.FrontendProvider; import p.studio.compiler.services.PBSFrontendPhaseService; +import java.util.Optional; + public final class PBSFrontendProvider implements FrontendProvider { private final FrontendPhaseService compiler; + private final PBSFrontendLanguageService languageService; public PBSFrontendProvider() { - this(new PBSFrontendPhaseService()); + this(new PBSFrontendPhaseService(), new PBSFrontendLanguageService()); } PBSFrontendProvider(final FrontendPhaseService compiler) { + this(compiler, new PBSFrontendLanguageService()); + } + + PBSFrontendProvider( + final FrontendPhaseService compiler, + final PBSFrontendLanguageService languageService) { this.compiler = compiler; + this.languageService = languageService; } @Override @@ -25,4 +36,9 @@ public final class PBSFrontendProvider implements FrontendProvider { public FrontendPhaseService compiler() { return compiler; } + + @Override + public Optional languageService() { + return Optional.of(languageService); + } } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java index 06244fc6..3ddd882a 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java @@ -4,8 +4,8 @@ import org.junit.jupiter.api.Test; import p.studio.compiler.services.PBSFrontendPhaseService; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; class PBSFrontendProviderTest { @@ -15,6 +15,7 @@ class PBSFrontendProviderTest { assertEquals(PBSDefinitions.PBS.getLanguageId(), provider.specification().getLanguageId()); assertInstanceOf(PBSFrontendPhaseService.class, provider.compiler()); - assertFalse(provider.languageService().isPresent()); + assertTrue(provider.languageService().isPresent()); + assertInstanceOf(PBSFrontendLanguageService.class, provider.languageService().orElseThrow()); } } -- 2.47.2 From fee89d752258b515dc070e37f6153ea907651084 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 09:43:30 +0100 Subject: [PATCH 3/5] implements PLN-0109 --- discussion/index.ndjson | 2 +- ...ke-lsp-editorial-calls-capability-aware.md | 2 +- .../CompilerLanguageServiceBridge.java | 41 ++++++++++++++----- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 9bbf5c5d..9d7be19c 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -9,7 +9,7 @@ {"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-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0052","status":"open","ticket":"pbs-lsp-document-links","title":"PBS LSP Document Links","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","document-links","imports"],"agendas":[{"id":"AGD-0055","file":"AGD-0055-pbs-lsp-document-links.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md b/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md index ea7bcf36..221f8bc7 100644 --- a/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md +++ b/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md @@ -2,7 +2,7 @@ id: PLN-0109 ticket: multi-frontend-compiler-vs-language-services title: Make LSP editorial calls capability aware -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0041] tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index e7196e61..980ed8f4 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -2,6 +2,7 @@ package p.studio.lsp.services.compiler; import org.apache.commons.lang3.StringUtils; import p.studio.compiler.FrontendRegistryService; +import p.studio.compiler.PBSFrontendLanguageService; import p.studio.compiler.messages.*; import p.studio.compiler.models.*; import p.studio.compiler.pbs.semantics.*; @@ -21,7 +22,6 @@ import java.util.*; public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { private final AssetSurfaceContextLoader assetSurfaceContextLoader = new AssetSurfaceContextLoader(); - private final PbsEditorialSupportService editorialSupportService = new PbsEditorialSupportService(); @Override public BaselineServerDescription describeServer(final LspProjectContext context) { @@ -61,10 +61,14 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg final int line, final int character) { Objects.requireNonNull(context, "context"); + final Optional languageService = pbsLanguageService(context); + if (languageService.isEmpty()) { + return new BaselineCompletion(false, List.of()); + } return editorialDocument(context, documentUri, text) .map(document -> { final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); - final List candidates = editorialSupportService.completion( + final List candidates = languageService.orElseThrow().completion( document.text(), document.ast(), document.supplementalTopDecls(), @@ -85,10 +89,14 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg final int line, final int character) { Objects.requireNonNull(context, "context"); + final Optional languageService = pbsLanguageService(context); + if (languageService.isEmpty()) { + return new BaselineHover("No symbol information."); + } return editorialDocument(context, documentUri, text) .flatMap(document -> { final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); - return editorialSupportService.hover( + return languageService.orElseThrow().hover( document.text(), document.ast(), document.supplementalTopDecls(), @@ -107,10 +115,14 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg final int line, final int character) { Objects.requireNonNull(context, "context"); + final Optional languageService = pbsLanguageService(context); + if (languageService.isEmpty()) { + return new BaselineSignatureHelp(List.of(), 0, 0); + } return editorialDocument(context, documentUri, text) .flatMap(document -> { final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); - return editorialSupportService.signatureHelp( + return languageService.orElseThrow().signatureHelp( document.text(), document.ast(), document.supplementalTopDecls(), @@ -133,9 +145,11 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg final String text) { Objects.requireNonNull(context, "context"); final String effectiveText = text == null ? "" : text; - final var frontend = frontendSpec(context); + final var frontend = frontendProvider(context).specification(); final FrontendSemanticPresentationSpec presentation = frontend.getSemanticPresentation(); - final List tokens = frontend.getSemanticTokenProvider().tokenize(effectiveText); + final List tokens = pbsLanguageService(context) + .map(languageService -> languageService.semanticTokens(effectiveText)) + .orElseGet(List::of); final var positionMapper = new DocumentPositionMapper(effectiveText); final var semanticTokens = new ArrayList(); @@ -177,9 +191,6 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg final LspProjectContext context, final String documentUri, final String text) { - if (!"pbs".equals(context.languageId())) { - return Optional.empty(); - } final Path documentPath = normalizeDocumentPath(documentUri); final BuilderPipelineContext pipelineContext = BuilderPipelineContext.fromConfig( new BuilderPipelineConfig( @@ -335,10 +346,20 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg } private p.studio.compiler.models.FrontendSpec frontendSpec(final LspProjectContext context) { - return FrontendRegistryService.getFrontendSpec(context.languageId()) + return frontendProvider(context).specification(); + } + + private p.studio.compiler.services.FrontendProvider frontendProvider(final LspProjectContext context) { + return FrontendRegistryService.getProvider(context.languageId()) .orElseThrow(() -> new IllegalArgumentException("no frontend registered for languageId: " + context.languageId())); } + private Optional pbsLanguageService(final LspProjectContext context) { + return frontendProvider(context).languageService() + .filter(PBSFrontendLanguageService.class::isInstance) + .map(PBSFrontendLanguageService.class::cast); + } + private BaselineCompletionItemKind mapCompletionKind(final PbsEditorialSymbolKind kind) { return switch (kind) { case KEYWORD -> BaselineCompletionItemKind.KEYWORD; -- 2.47.2 From da00e9c50c2463fddde6824b9afd849ede03d105 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 09:45:49 +0100 Subject: [PATCH 4/5] implements PLN-0110 --- discussion/index.ndjson | 2 +- ...-absent-capability-conformance-coverage.md | 2 +- .../specs/FrontendProviderBoundaryTest.java | 80 +++++++++++++++++++ .../CompilerLanguageServiceBridge.java | 16 +++- .../CompilerLanguageServiceBridgeTest.java | 68 ++++++++++++++++ 5 files changed, 163 insertions(+), 5 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 9d7be19c..1560931e 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -9,7 +9,7 @@ {"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-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0052","status":"open","ticket":"pbs-lsp-document-links","title":"PBS LSP Document Links","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","document-links","imports"],"agendas":[{"id":"AGD-0055","file":"AGD-0055-pbs-lsp-document-links.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md b/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md index b0257383..cd4990b6 100644 --- a/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md +++ b/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md @@ -2,7 +2,7 @@ id: PLN-0110 ticket: multi-frontend-compiler-vs-language-services title: Add compile only frontend and absent capability conformance coverage -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0041] tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java index a69363d6..6ea8fef5 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java @@ -1,12 +1,23 @@ package p.studio.compiler.specs; import org.junit.jupiter.api.Test; +import p.studio.compiler.messages.BuildingIssueSink; +import p.studio.compiler.messages.FrontendPhaseContext; +import p.studio.compiler.models.FrontendSpec; +import p.studio.compiler.models.IRBackend; +import p.studio.compiler.services.FrontendPhaseService; +import p.studio.compiler.services.FrontendProvider; +import p.studio.compiler.source.diagnostics.DiagnosticSink; +import p.studio.utilities.logs.LogAggregator; +import p.studio.utilities.structures.ReadOnlySet; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; class FrontendProviderBoundaryTest { @@ -37,6 +48,45 @@ class FrontendProviderBoundaryTest { } } + @Test + void commonModulesMustNotInstantiatePbsEditorialSupportServiceDirectly() throws IOException { + final var repoRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize()); + final var sourceRoots = List.of( + repoRoot.resolve("prometeu-compiler/prometeu-build-pipeline/src/main/java"), + repoRoot.resolve("prometeu-compiler/prometeu-deps/src/main/java"), + repoRoot.resolve("prometeu-lsp/prometeu-lsp-v1/src/main/java"), + repoRoot.resolve("prometeu-studio/src/main/java"), + repoRoot.resolve("prometeu-app/src/main/java")); + + for (final var sourceRoot : sourceRoots) { + if (!Files.exists(sourceRoot)) { + continue; + } + + try (final var files = Files.walk(sourceRoot)) { + final var violations = files + .filter(path -> path.toString().endsWith(".java")) + .filter(path -> contains(path, "new PbsEditorialSupportService(")) + .toList(); + if (!violations.isEmpty()) { + fail("common modules must resolve PBS editor behavior through FrontendProvider.languageService(): " + violations); + } + } + } + } + + @Test + void compileOnlyFrontendProviderMayOmitLanguageService() { + final FrontendProvider provider = new CompileOnlyFrontendProvider(); + + assertTrue(provider.languageService().isEmpty()); + assertNotNull(provider.compiler().compile( + null, + DiagnosticSink.empty(), + LogAggregator.empty(), + BuildingIssueSink.empty())); + } + private boolean contains(final Path path, final String needle) { try { return Files.readString(path).contains(needle); @@ -56,4 +106,34 @@ class FrontendProviderBoundaryTest { fail("unable to locate repository root from " + start); return start; } + + private static final class CompileOnlyFrontendProvider implements FrontendProvider { + private final FrontendSpec specification = FrontendSpec.builder() + .languageId("compile-only") + .allowedExtensions(ReadOnlySet.from("co")) + .sourceRoots(ReadOnlySet.from("src")) + .build(); + private final FrontendPhaseService compiler = new CompileOnlyFrontendPhaseService(); + + @Override + public FrontendSpec specification() { + return specification; + } + + @Override + public FrontendPhaseService compiler() { + return compiler; + } + } + + private static final class CompileOnlyFrontendPhaseService implements FrontendPhaseService { + @Override + public IRBackend compile( + final FrontendPhaseContext request, + final DiagnosticSink diagnostics, + final LogAggregator logs, + final BuildingIssueSink issues) { + return IRBackend.builder().build(); + } + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 980ed8f4..37e27159 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -6,6 +6,7 @@ import p.studio.compiler.PBSFrontendLanguageService; import p.studio.compiler.messages.*; import p.studio.compiler.models.*; import p.studio.compiler.pbs.semantics.*; +import p.studio.compiler.services.FrontendProvider; import p.studio.compiler.services.PBSFrontendPhaseService; import p.studio.compiler.source.identifiers.FileId; import p.studio.compiler.utilities.SourceProviderFactory; @@ -19,9 +20,19 @@ import p.studio.utilities.structures.ReadOnlyList; import java.net.URI; import java.nio.file.Path; import java.util.*; +import java.util.function.Function; public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { private final AssetSurfaceContextLoader assetSurfaceContextLoader = new AssetSurfaceContextLoader(); + private final Function frontendProviderResolver; + + public CompilerLanguageServiceBridge() { + this(FrontendRegistryService::require); + } + + CompilerLanguageServiceBridge(final Function frontendProviderResolver) { + this.frontendProviderResolver = Objects.requireNonNull(frontendProviderResolver, "frontendProviderResolver"); + } @Override public BaselineServerDescription describeServer(final LspProjectContext context) { @@ -349,9 +360,8 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg return frontendProvider(context).specification(); } - private p.studio.compiler.services.FrontendProvider frontendProvider(final LspProjectContext context) { - return FrontendRegistryService.getProvider(context.languageId()) - .orElseThrow(() -> new IllegalArgumentException("no frontend registered for languageId: " + context.languageId())); + private FrontendProvider frontendProvider(final LspProjectContext context) { + return frontendProviderResolver.apply(context.languageId()); } private Optional pbsLanguageService(final LspProjectContext context) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 12be85a8..7efb440d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -1,8 +1,17 @@ package p.studio.lsp.services.compiler; import org.junit.jupiter.api.Test; +import p.studio.compiler.messages.BuildingIssueSink; +import p.studio.compiler.messages.FrontendPhaseContext; +import p.studio.compiler.models.FrontendSpec; +import p.studio.compiler.models.IRBackend; +import p.studio.compiler.services.FrontendPhaseService; +import p.studio.compiler.services.FrontendProvider; +import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.lsp.messages.BaselineIssueSeverity; import p.studio.lsp.messages.LspProjectContext; +import p.studio.utilities.logs.LogAggregator; +import p.studio.utilities.structures.ReadOnlySet; import java.nio.file.Files; import java.nio.file.Path; @@ -12,6 +21,35 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class CompilerLanguageServiceBridgeTest { + @Test + void editorialEndpointsReturnNeutralResponsesWhenLanguageServiceIsAbsent() { + final var provider = new CompileOnlyFrontendProvider(); + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(languageId -> { + if (provider.specification().getLanguageId().equals(languageId)) { + return provider; + } + throw new IllegalArgumentException("no frontend registered for languageId: " + languageId); + }); + final LspProjectContext context = new LspProjectContext("main", provider.specification().getLanguageId(), Path.of(".")); + final String documentUri = Path.of("demo.co").toUri().toString(); + + final var completion = bridge.completion(context, documentUri, "fn main() {}", 0, 0); + assertFalse(completion.incomplete()); + assertTrue(completion.items().isEmpty()); + + final var hover = bridge.hover(context, documentUri, "fn main() {}", 0, 0); + assertEquals("No symbol information.", hover.markdown()); + + final var signatureHelp = bridge.signatureHelp(context, documentUri, "fn main() {}", 0, 0); + assertTrue(signatureHelp.signatures().isEmpty()); + assertEquals(0, signatureHelp.activeSignature()); + assertEquals(0, signatureHelp.activeParameter()); + + final var semanticTokens = bridge.semanticTokens(context, documentUri, "fn main() {}"); + assertTrue(semanticTokens.legend().isEmpty()); + assertTrue(semanticTokens.tokens().isEmpty()); + } + @Test void analyzeDocumentReturnsCompilerDiagnosticsForOverlayContent() { final Path projectRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize()) @@ -305,4 +343,34 @@ class CompilerLanguageServiceBridgeTest { } throw new IllegalStateException("unable to locate repository root from " + start); } + + private static final class CompileOnlyFrontendProvider implements FrontendProvider { + private final FrontendSpec specification = FrontendSpec.builder() + .languageId("compile-only") + .allowedExtensions(ReadOnlySet.from("co")) + .sourceRoots(ReadOnlySet.from("src")) + .build(); + private final FrontendPhaseService compiler = new CompileOnlyFrontendPhaseService(); + + @Override + public FrontendSpec specification() { + return specification; + } + + @Override + public FrontendPhaseService compiler() { + return compiler; + } + } + + private static final class CompileOnlyFrontendPhaseService implements FrontendPhaseService { + @Override + public IRBackend compile( + final FrontendPhaseContext request, + final DiagnosticSink diagnostics, + final LogAggregator logs, + final BuildingIssueSink issues) { + return IRBackend.builder().build(); + } + } } -- 2.47.2 From 4233b90b822ce1d32595dd635ca1ec2f41874d69 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 09:55:08 +0100 Subject: [PATCH 5/5] housekeep DSC-0055 --- discussion/index.ndjson | 4 +- ...ds-with-optional-editorial-capabilities.md | 88 +++++++++++++++ ...-frontend-compiler-vs-language-services.md | 78 ------------- ...lation-from-editorial-language-services.md | 104 ------------------ ...piler-and-editorial-capability-boundary.md | 68 ------------ ...stance-behind-optional-language-service.md | 71 ------------ ...ke-lsp-editorial-calls-capability-aware.md | 74 ------------- ...-absent-capability-conformance-coverage.md | 72 ------------ 8 files changed, 90 insertions(+), 469 deletions(-) create mode 100644 discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md delete mode 100644 discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md delete mode 100644 discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md delete mode 100644 discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md delete mode 100644 discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md delete mode 100644 discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md delete mode 100644 discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 1560931e..5049fb8e 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":56,"CLSN":1}} +{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":42,"PLN":111,"LSN":57,"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":[]} @@ -9,7 +9,7 @@ {"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-0055","status":"in_progress","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":[{"id":"AGD-0058","file":"AGD-0058-multi-frontend-compiler-vs-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-separate-frontend-compilation-from-editorial-language-services.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0058"}],"plans":[{"id":"PLN-0107","file":"PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0108","file":"PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0109","file":"PLN-0109-make-lsp-editorial-calls-capability-aware.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]},{"id":"PLN-0110","file":"PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0041"]}],"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":[]} {"type":"discussion","id":"DSC-0052","status":"open","ticket":"pbs-lsp-document-links","title":"PBS LSP Document Links","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","document-links","imports"],"agendas":[{"id":"AGD-0055","file":"AGD-0055-pbs-lsp-document-links.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md b/discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md new file mode 100644 index 00000000..76860be1 --- /dev/null +++ b/discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md @@ -0,0 +1,88 @@ +# Compile-first frontends with optional editorial capabilities + +## Original Problem + +Prometeu is moving from a PBS-centered compiler/editor stack toward a multi-frontend compiler. PBS already provides compilation plus rich editor assistance, so it was easy for shared code, LSP, or Studio consumers to assume that every frontend can provide diagnostics, semantic tokens, completion, hover, and signature help as one package. + +That assumption makes future frontend adoption too expensive. A new frontend must be able to compile before it has a complete IDE experience. + +## Consolidated Decision + +The frontend contract is compile-first. + +Every frontend must provide a compiler capability through `FrontendProvider.compiler()`. Editorial services are optional and live behind `FrontendProvider.languageService()`. + +A frontend that can compile but has no language service is valid. Missing editor assistance must not block `analyze`, `compile`, `build`, backend lowering, bytecode emission, verification, or artifact writing. + +LSP and Studio consumers must query editorial capability before invoking editor-specific behavior. Absence of a capability is a normal state, not a compiler failure. + +## Final Implementation + +The compiler pipeline spec now defines the provider boundary explicitly: + +- `compiler()` is the only required executable frontend capability. +- `languageService()` is optional. +- editor capabilities such as completion, hover, definition, signature help, semantic tokens, formatting, rename, and code actions are optional unless a future accepted decision narrows the requirement. +- absent editor capabilities have deterministic fallback behavior. +- compiler diagnostics and editor diagnostics are separate ownership surfaces. + +PBS keeps its rich editor assistance, but now exposes it through `PBSFrontendLanguageService`, returned by `PBSFrontendProvider.languageService()`. + +The LSP bridge resolves the active `FrontendProvider` and checks for `languageService()` before using editor behavior. For now, PBS remains an adapter-specific implementation because the common language-service DTOs are not yet generalized. That is acceptable because the important boundary is already enforced: the LSP no longer assumes that compiler support implies editor support. + +Conformance coverage now includes: + +- a compile-only provider fixture with no language service; +- LSP neutral responses when editor capability is absent; +- PBS regression coverage for existing completion, hover, signature help, semantic tokens, and documentation behavior; +- architecture tests preventing common modules from directly instantiating PBS editor support. + +## Examples + +A compile-only frontend should look like this at the provider boundary: + +```java +public final class ExampleFrontendProvider implements FrontendProvider { + @Override + public FrontendSpec specification() { + return EXAMPLE_SPEC; + } + + @Override + public FrontendPhaseService compiler() { + return exampleCompiler; + } +} +``` + +It does not need to override `languageService()`. The default empty optional is a valid frontend state. + +An editor consumer should treat missing services as a normal fallback: + +```java +return provider.languageService() + .filter(ExpectedLanguageService.class::isInstance) + .map(ExpectedLanguageService.class::cast) + .map(service -> service.completion(...)) + .orElseGet(List::of); +``` + +## Pitfalls + +Do not use PBS as the minimum frontend contract. PBS is the first rich frontend, not the definition of frontend validity. + +Do not make editor diagnostics a prerequisite for compilation. Build/analyze diagnostics are compiler output; live editor diagnostics may reuse compiler results but have different latency, cancellation, overlay, and UX concerns. + +Do not split the language service into many top-level interfaces before implementation pressure proves a real lifecycle or ownership boundary. The current contract intentionally keeps an aggregated optional language-service surface. + +Do not call PBS editorial classes directly from common compiler, LSP, Studio, or app code. Go through `FrontendProvider.languageService()` and adapter-local capability checks. + +## References + +- Spec: `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` +- Provider API: `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java` +- PBS language service: `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java` +- LSP bridge: `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` +- Conformance tests: + - `prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java` + - `prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java` diff --git a/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md b/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md deleted file mode 100644 index 6639083e..00000000 --- a/discussion/workflow/agendas/AGD-0058-multi-frontend-compiler-vs-language-services.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -id: AGD-0058 -ticket: multi-frontend-compiler-vs-language-services -title: Separar compilacao de servicos editoriais de frontend -status: accepted -created: 2026-07-15 -resolved: -decision: -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -# Agenda - Separar compilacao de servicos editoriais - -## Objetivo - -Domain owner: `compiler/general`, com impacto em `studio/lsp`. - -Separar o contrato necessario para build do contrato necessario para IDE, permitindo frontends progressivos: compilacao, diagnostics/highlighting e experiencia editorial completa. - -## Contexto atual - -O PBS fornece compilacao e varias superficies editoriais. Historicamente o Studio e o LSP podem assumir que semantic tokens, diagnostics e navegação vêm do mesmo servico PBS. - -## Escopo - -- Identificar interfaces atuais de compilacao e editor. -- Definir capabilities opcionais para servicos editoriais. -- Garantir que ausencia de completion, hover, definition ou semantic tokens nao invalide um frontend compilavel. - -## Fora de escopo - -- Implementar novas features editoriais. -- Redesenhar todo o LSP. -- Criar frontend real sem recursos editoriais. - -## Arquivos e componentes a inspecionar - -- `prometeu-lsp/prometeu-lsp-api/...` -- `prometeu-lsp/...` -- `prometeu-studio/src/main/java/p/studio/...editor...` -- `prometeu-compiler/frontends/prometeu-frontend-pbs/...` -- `prometeu-compiler/prometeu-build-pipeline/...` - -## Alteracoes propostas - -Opcao A: `FrontendProvider` entrega `FrontendCompiler` obrigatorio e `Optional`. - -Opcao B: dividir language service em interfaces menores, como diagnostics, completion, hover, definition e semantic tokens. - -Recomendacao inicial: mapear primeiro os consumidores. Se o LSP ja resolve features separadamente, usar interfaces menores; caso contrario, um language service opcional com capabilities pode ser suficiente. - -## Estrategia de implementacao - -Caracterizar o comportamento PBS atual, definir fallback para recurso ausente e migrar chamadas editoriais para consulta de capability antes de invocar servico. - -## Testes necessarios - -- Frontend provider compilavel sem language service nao quebra build. -- LSP/Studio tratam feature ausente como resposta vazia ou unsupported documentado. -- PBS continua expondo as mesmas respostas editoriais. - -## Criterios de aceitacao - -- Compilacao nao depende de APIs de IDE. -- Recursos editoriais ausentes sao opcionais. -- O contrato permite os niveis 1, 2 e 3 descritos no alinhamento. - -## Riscos - -- Introduzir `Optional` em excesso sem uma politica consistente de fallback. -- Acoplar diagnostics de build e diagnostics editoriais sem separar latencia e escopo. - -## Decisoes que devem ser registradas - -- Granularidade final das interfaces editoriais. -- Comportamento padrao para capability ausente. -- Relacao entre diagnostics de compilacao e diagnostics de editor. - diff --git a/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md b/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md deleted file mode 100644 index 96d0adea..00000000 --- a/discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -id: DEC-0041 -ticket: multi-frontend-compiler-vs-language-services -title: Separate frontend compilation from editorial language services -status: accepted -created: 2026-07-15 -ref_agenda: AGD-0058 -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -## Context - -Prometeu is preparing the compiler and editor stack for multiple frontends. PBS currently provides compilation and rich editor assistance, and existing LSP/Studio paths can still assume that diagnostics, semantic tokens, completion, hover, and signature help are all backed by the PBS frontend implementation. - -This decision belongs to domain owner `compiler/general`. - -Touched subdomains: - -- `studio/lsp` -- `compiler/pbs` - -The existing API already points in the right direction: `FrontendProvider` exposes mandatory compiler behavior through `compiler()` and optional editor behavior through `languageService()`. However, the LSP bridge still contains PBS-specific editorial logic, so the boundary needs to be made normative before implementation plans migrate consumers. - -This decision resolves `AGD-0058`. - -## Decision - -Frontend compilation and editorial language services MUST be separate contracts. - -Every frontend MUST provide a compiler contract. A frontend MAY provide editorial language services. A frontend that can compile but does not provide completion, hover, definition, signature help, semantic tokens, or other editor assistance MUST still be considered a valid frontend. - -`FrontendProvider.compiler()` is the required frontend capability. It MUST remain sufficient for build, analyze, compile, and backend-facing pipeline flows. - -`FrontendProvider.languageService()` is the optional editorial capability boundary. The absence of a language service MUST NOT prevent compilation, project analysis, or backend execution. - -The first common editorial contract SHOULD remain aggregated as `FrontendLanguageService` plus explicit capabilities, rather than immediately splitting every feature into separate top-level service interfaces. Smaller feature interfaces MAY be introduced later when implementation pressure proves that independent ownership, testing, or lifecycle is needed. - -LSP and Studio consumers MUST query editorial capability availability before invoking editor-specific behavior. They MUST NOT assume that a frontend with a compiler also supports completion, hover, definition, semantic tokens, signature help, formatting, rename, code actions, or similar editor features. - -When an editorial capability is absent, LSP and Studio MUST degrade gracefully: - -- collection-shaped responses SHOULD be empty; -- scalar optional responses SHOULD be absent or use a documented neutral response; -- protocol-level unsupported behavior SHOULD be explicit when the host protocol supports that distinction; -- absence MUST NOT be reported as a compiler failure. - -PBS MAY continue to expose the rich editorial behavior it has today. That behavior is a PBS-provided capability, not a requirement imposed on all future frontends. - -Compiler diagnostics and editorial diagnostics MUST remain distinct concepts. Build/analyze diagnostics belong to the compiler contract. Editorial diagnostics MAY reuse compiler analysis results, but a frontend MUST NOT be required to provide a separate editor diagnostics service in order to compile. - -Semantic presentation metadata, such as frontend-owned semantic token vocabularies and visual themes, remains frontend-owned presentation data. Producing semantic tokens for a live document is an editorial capability and MUST be optional unless a future decision narrows that requirement for a specific host. - -The LSP implementation SHOULD migrate from direct PBS editorial calls toward resolving the active frontend provider and consulting its optional language-service capabilities. Until that migration is planned and implemented, PBS-specific bridge code is tolerated as legacy coupling, not as the normative architecture. - -## Rationale - -Multi-frontend support requires a low floor: a new language frontend should be able to join the build pipeline before it has IDE-grade assistance. Requiring all editor features up front would turn frontend adoption into a large all-or-nothing task and would couple compiler correctness to UX completeness. - -Keeping the first editorial boundary aggregated avoids premature interface explosion. The codebase already has a marker `FrontendLanguageService`, while the real uncertainty is how LSP/Studio should discover and handle absent capabilities. Capability negotiation solves that problem without forcing a final taxonomy before there is enough implementation evidence. - -Separating compiler diagnostics from editorial diagnostics protects latency and ownership boundaries. Build diagnostics can be produced as part of normal analysis, while editor diagnostics may need live overlays, partial results, cancellation, caching, or host-specific behavior. - -PBS should remain the reference rich frontend, but it should not define the minimum contract for all future languages. Treating PBS editor support as optional capability data makes the current implementation useful without freezing PBS assumptions into the common compiler API. - -## Implications - -- Common compiler code MUST depend on the compiler capability, not on PBS-specific frontend services. -- LSP/Studio code that invokes editor behavior MUST handle absent capabilities deterministically. -- Existing PBS editor assistance should be preserved while being moved behind the common optional language-service boundary over time. -- Future frontend tests should include at least one compile-capable frontend with no language service. -- Future LSP/Studio tests should prove that absent capabilities produce empty or unsupported responses rather than build failures. -- Introducing smaller editorial interfaces is allowed later, but only after a plan identifies real feature lifecycle boundaries. -- Plans derived from this decision MUST NOT reinterpret optional editorial services as required for frontend validity. - -## Propagation Targets - -- specs: - - `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` - - A future compiler/frontend provider contract spec if one is created. - - LSP/editor-facing specs if/when a dedicated Studio/LSP spec surface exists. -- plans: - - Create a plan to specify the frontend provider/editorial capability boundary. - - Create a plan to migrate LSP/Studio consumers away from direct PBS editorial assumptions. -- code: - - `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java` - - `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` - - `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` - - PBS frontend editorial support classes. -- tests: - - Frontend provider tests proving compilation works without a language service. - - LSP/Studio tests for absent completion, hover, signature help, semantic tokens, and future editorial capabilities. - - Regression tests proving PBS still exposes current editorial behavior. -- docs: - - Specs updated by implementation plans. - - Lessons generated after implementation and housekeeping. - -## References - -- Agenda: AGD-0058 -- Source discussion: DSC-0055 - -## Revision Log - -- 2026-07-15: Initial decision drafted from accepted `AGD-0058`. diff --git a/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md b/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md deleted file mode 100644 index 0c4d1d05..00000000 --- a/discussion/workflow/plans/PLN-0107-specify-frontend-compiler-and-editorial-capability-boundary.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: PLN-0107 -ticket: multi-frontend-compiler-vs-language-services -title: Specify frontend compiler and editorial capability boundary -status: done -created: 2026-07-15 -ref_decisions: [DEC-0041] -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -## Briefing - -`DEC-0041` makes compilation mandatory and editorial language services optional for every frontend. This plan updates the normative compiler-facing documentation so future implementation work has a precise boundary to follow. - -## Objective - -Document the frontend provider contract: compiler capability is required, editorial capabilities are optional, and absent editorial support must not invalidate build, analyze, compile, or backend flows. - -## Dependencies - -- Accepted decision: `DEC-0041`. -- Existing `FrontendProvider.compiler()` and `FrontendProvider.languageService()` API shape. -- Existing compiler pipeline entrypoint specification. - -## Scope - -- Update compiler specs to state that `FrontendProvider.compiler()` is the required frontend capability. -- Define `FrontendProvider.languageService()` as the optional editorial capability boundary. -- Document expected fallback behavior for absent editorial capabilities at the compiler/LSP boundary. -- Document that build/analyze diagnostics are compiler diagnostics, while editor diagnostics are optional editorial behavior. -- Add a short capability vocabulary for completion, hover, definition, signature help, semantic tokens, formatting, rename, and code actions without requiring all of them to exist now. - -## Non-Goals - -- Implement Java API changes. -- Migrate PBS editor assistance. -- Change LSP behavior. -- Split `FrontendLanguageService` into many top-level interfaces. -- Choose a plugin or process model for external frontends. - -## Execution Method - -1. Update `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` with a subsection for frontend provider capability boundaries. -2. State that compiler entrypoints must depend on the compiler capability only and must not require editorial services. -3. Define optional editorial capabilities as host-facing editor assistance, not backend-facing compilation requirements. -4. Record fallback semantics: absent collection-shaped editorial results are empty, absent scalar results are neutral/absent, and protocol unsupported states are explicit where available. -5. Document diagnostics ownership: build/analyze diagnostics are compiler contract output; editor diagnostics may reuse compiler analysis but are not required for frontend validity. -6. Add cross-references to `DEC-0041` and existing frontend provider docs or lessons where appropriate. - -## Acceptance Criteria - -- The compiler spec explicitly separates required compiler capability from optional editorial capability. -- The spec states that compile-capable frontends with no language service are valid. -- The spec states that absent editorial capability is not a compiler failure. -- The spec does not require JSON, RPC, plugin loading, out-of-process frontends, or a wire format. -- The spec keeps `FrontendLanguageService` aggregated for now and does not mandate premature feature-interface splitting. - -## Tests - -- Documentation-only plan: run `discussion validate` after updates. -- If markdown/spec linting exists locally, run the relevant docs validation task. -- Future implementation tests are delegated to `PLN-0110`. - -## Affected Artifacts - -- `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` -- `discussion/workflow/decisions/DEC-0041-separate-frontend-compilation-from-editorial-language-services.md` -- This plan. diff --git a/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md b/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md deleted file mode 100644 index de41ce38..00000000 --- a/discussion/workflow/plans/PLN-0108-move-pbs-editor-assistance-behind-optional-language-service.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: PLN-0108 -ticket: multi-frontend-compiler-vs-language-services -title: Move PBS editor assistance behind optional language service -status: done -created: 2026-07-15 -ref_decisions: [DEC-0041] -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -## Briefing - -`DEC-0041` allows PBS to keep rich editor assistance, but that behavior must become a PBS-provided optional capability instead of a common frontend requirement. This plan moves PBS completion, hover, signature help, semantic token production, and related editorial behavior behind the optional language-service boundary. - -## Objective - -Expose PBS editor assistance through `FrontendProvider.languageService()` while preserving current PBS behavior and keeping `FrontendProvider.compiler()` sufficient for compilation. - -## Dependencies - -- Accepted decision: `DEC-0041`. -- `PLN-0107` should define the documented boundary before final implementation review. -- Existing PBS editorial support classes and LSP bridge behavior. - -## Scope - -- Introduce or extend PBS language-service implementation under the PBS frontend module. -- Make `PBSFrontendProvider.languageService()` return a PBS language service. -- Keep `PBSFrontendProvider.compiler()` unchanged as the required compiler path. -- Move PBS-specific editorial calls into the PBS language-service implementation or adapter. -- Preserve existing completion, hover, signature help, semantic token, and documentation behavior for PBS. - -## Non-Goals - -- Change PBS language semantics. -- Add new editor features. -- Rewrite the LSP protocol layer. -- Implement capability-aware LSP fallbacks; that belongs to `PLN-0109`. -- Split every editor feature into independent top-level service interfaces unless strictly required by local implementation shape. - -## Execution Method - -1. Inspect `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` and define the minimum capability accessors needed by current PBS editor behavior. -2. Add a PBS language-service implementation in the PBS frontend module, colocated with existing PBS editorial support classes. -3. Move or delegate completion, hover, signature help, and semantic token behavior from PBS-specific bridge code into the PBS language-service implementation without changing output models unless the boundary requires neutral compiler-facing DTOs. -4. Update `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java` to return `Optional.of(pbsLanguageService)`. -5. Keep compile/analyze/build paths independent of `languageService()`. -6. Preserve current PBS editorial tests by redirecting setup to the new PBS language-service surface where appropriate. - -## Acceptance Criteria - -- PBS provider exposes a non-empty optional language service. -- PBS compilation still works when only `compiler()` is used. -- PBS completion, hover, signature help, semantic tokens, and documentation behavior remain equivalent to current behavior. -- Common compiler modules do not instantiate PBS editorial implementation directly. -- No new requirement is introduced for non-PBS frontends to implement editor assistance. - -## Tests - -- Run PBS frontend tests covering editorial support. -- Run LSP tests that currently assert PBS completion, hover, signature help, semantic tokens, and documentation behavior. -- Add or update provider tests proving PBS has a language service while a compile-only provider can omit it. -- Run targeted Gradle tasks for changed compiler frontend and LSP modules. - -## Affected Artifacts - -- `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java` -- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java` -- PBS editorial support classes under `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java` -- Related PBS frontend tests. -- Related LSP bridge tests. diff --git a/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md b/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md deleted file mode 100644 index 221f8bc7..00000000 --- a/discussion/workflow/plans/PLN-0109-make-lsp-editorial-calls-capability-aware.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: PLN-0109 -ticket: multi-frontend-compiler-vs-language-services -title: Make LSP editorial calls capability aware -status: done -created: 2026-07-15 -ref_decisions: [DEC-0041] -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -## Briefing - -`DEC-0041` requires LSP and Studio consumers to query editorial capability availability before invoking editor-specific behavior. The current LSP bridge still contains PBS-specific editorial logic. This plan migrates LSP editorial calls to capability-aware provider lookup and graceful fallbacks. - -## Objective - -Make LSP completion, hover, signature help, semantic tokens, and future editorial calls resolve the active frontend provider, consult optional language-service capabilities, and return deterministic neutral responses when capabilities are absent. - -## Dependencies - -- Accepted decision: `DEC-0041`. -- `PLN-0108` should expose PBS editor assistance through `FrontendProvider.languageService()`. -- Existing `FrontendRegistryService` frontend lookup. -- Existing LSP baseline messages and tests. - -## Scope - -- Update LSP bridge code to resolve frontend providers rather than hard-coding PBS editorial paths. -- Add fallback behavior for absent completion, hover, signature help, and semantic token capability. -- Preserve compiler-backed diagnostics through analyze/build paths. -- Keep PBS editorial behavior stable when its language service is present. -- Document or encode unsupported/neutral responses according to existing LSP baseline message shapes. - -## Non-Goals - -- Add new LSP features. -- Change VSCode extension behavior beyond consuming existing baseline responses. -- Remove all PBS-specific code in one step if adapter compatibility still requires local mapping. -- Make semantic presentation metadata optional; only live semantic token production is optional. - -## Execution Method - -1. Inspect `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java` and identify all direct PBS editorial calls. -2. Add a provider-resolution path using `FrontendRegistryService` or the existing registry abstraction for `context.languageId()`. -3. For each editorial endpoint, query `provider.languageService()` and then the relevant capability before invoking implementation behavior. -4. Return neutral fallbacks when absent: - - completion: incomplete `false` with empty items; - - hover: absent/neutral hover content according to current baseline message constraints; - - signature help: empty signatures with stable active indices; - - semantic tokens: frontend legend/presentation where available and empty token list when live tokenization is absent. -5. Keep `analyzeDocument` compiler-diagnostic behavior on the compiler pipeline and do not require `languageService()`. -6. Update tests to cover both PBS-present and capability-absent frontends. - -## Acceptance Criteria - -- LSP editorial endpoints do not assume every compiler frontend has editor assistance. -- Absent editorial capabilities produce deterministic empty or neutral responses, not compiler failures. -- Compiler diagnostics still work without a language service. -- PBS editor assistance remains unchanged when PBS language service is available. -- Any remaining PBS-specific code is adapter-local and documented as temporary if not removed. - -## Tests - -- Add LSP tests for a compile-only frontend or stub provider with no language service. -- Preserve existing `CompilerLanguageServiceBridgeTest` coverage for PBS completion, hover, signature help, and semantic tokens. -- Add regression coverage that `analyzeDocument` returns compiler diagnostics independently of editorial services. -- Run targeted LSP module tests. - -## 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` -- LSP baseline message types only if neutral response representation is currently insufficient. -- Frontend registry integration points used by LSP. diff --git a/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md b/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md deleted file mode 100644 index cd4990b6..00000000 --- a/discussion/workflow/plans/PLN-0110-add-compile-only-frontend-and-absent-capability-conformance-coverage.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: PLN-0110 -ticket: multi-frontend-compiler-vs-language-services -title: Add compile only frontend and absent capability conformance coverage -status: done -created: 2026-07-15 -ref_decisions: [DEC-0041] -tags: [compiler, compiler-general, studio, lsp, editor, frontend, multi-frontend] ---- - -## Briefing - -`DEC-0041` requires proof that a frontend can compile without editor assistance and that LSP/Studio behavior remains deterministic when editorial capabilities are absent. This plan adds focused conformance coverage so future changes cannot accidentally make language services mandatory again. - -## Objective - -Add tests and lightweight fixtures proving compile-only frontends are valid, compiler diagnostics remain available, and absent editorial capabilities produce graceful fallback responses. - -## Dependencies - -- Accepted decision: `DEC-0041`. -- `PLN-0107` for documented contract language. -- `PLN-0109` for capability-aware LSP behavior before all fallback tests can pass. - -## Scope - -- Add a compile-only test frontend/provider fixture that implements compiler behavior and omits `languageService()`. -- Add provider boundary tests proving build/analyze/compile flows do not require editor services. -- Add LSP fallback tests for absent completion, hover, signature help, semantic tokens, and future editorial capability slots when present in the API. -- Add PBS regression tests proving rich PBS editor behavior remains available. -- Add architecture tests that prevent common compiler modules from depending on PBS-specific editor services. - -## Non-Goals - -- Build a production non-PBS frontend. -- Add a plugin loader. -- Add new editor features. -- Replace all PBS tests with generic frontend tests. -- Test external process or wire-format behavior. - -## Execution Method - -1. Locate existing provider and boundary tests, including `FrontendProviderBoundaryTest`. -2. Add a compile-only provider fixture in the narrowest test source set that can exercise the provider contract without production registration churn. -3. Write compiler-side tests asserting the fixture has a compiler, has no language service, and can participate in the relevant build/analyze/compile path selected for the fixture. -4. Add LSP tests using the compile-only or stub frontend path to assert neutral responses for absent editorial capabilities. -5. Preserve or extend PBS regression tests to show PBS still exposes completion, hover, signature help, semantic tokens, and documentation. -6. Add architecture assertions that common compiler/pipeline modules do not instantiate PBS editorial services directly. - -## Acceptance Criteria - -- At least one test frontend is compile-capable with `languageService()` empty. -- Compiler/pipeline tests prove editor services are not required for compilation or analysis. -- LSP tests prove absent editorial capabilities are handled without exceptions or compiler failures. -- PBS tests prove existing editorial behavior is still available. -- Tests do not depend on JSON, RPC, plugin loading, external processes, or future wire formats. - -## Tests - -- Run compiler frontend API/provider tests. -- Run build pipeline boundary tests. -- Run targeted LSP tests. -- Run any architecture/reflection tests added for the no-PBS-editorial-dependency rule. -- Run `discussion validate` after plan status or workflow updates. - -## Affected Artifacts - -- `prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java` -- Relevant frontend provider tests under `prometeu-compiler`. -- Relevant LSP tests under `prometeu-lsp/prometeu-lsp-v1/src/test/java` -- Test fixtures for a compile-only frontend/provider. -- This plan and linked workflow metadata. -- 2.47.2