From e99bb58453f1e453ee2c03398824c960e84ca713 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:24:56 +0100 Subject: [PATCH 1/6] Multi Provider FE content --- discussion/index.ndjson | 4 +- ...D-0057-multi-frontend-provider-contract.md | 17 +- ...der-explicito-como-contrato-de-frontend.md | 92 ++++++++++ ...frontend-provider-and-registry-contract.md | 71 ++++++++ ...introduce-frontendprovider-registry-api.md | 69 ++++++++ ...-wrap-pbs-frontend-as-explicit-provider.md | 73 ++++++++ ...ate-common-consumers-to-provider-lookup.md | 74 ++++++++ .../main/assets/.prometeu/cache.json | 162 +++++++++--------- 8 files changed, 478 insertions(+), 84 deletions(-) create mode 100644 discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md create mode 100644 discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md create mode 100644 discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md create mode 100644 discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md create mode 100644 discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 339be458..1bd164a4 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":40,"PLN":103,"LSN":55,"CLSN":1}} +{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":41,"PLN":107,"LSN":55,"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":[]} @@ -10,7 +10,7 @@ {"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-0054","status":"open","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md b/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md index d193aeae..dbb0267f 100644 --- a/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md +++ b/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md @@ -2,7 +2,7 @@ id: AGD-0057 ticket: multi-frontend-provider-contract title: Introduzir provider completo de frontend -status: open +status: accepted created: 2026-07-15 resolved: decision: @@ -77,3 +77,18 @@ Comecar por uma auditoria de chamadas atuais ao registry e de instanciacoes dire - Responsabilidades minimas do provider. - Onde fica o composition root autorizado a registrar PBS. +## Resolucao aceita + +O contrato deve ser introduzido como `FrontendProvider`. + +Responsabilidades minimas: + +- expor a especificacao do frontend por `specification()`; +- expor o compilador ou fase de compilacao equivalente por `compiler()`; +- expor servicos editoriais por `languageService()` somente como capacidade opcional, quando necessaria para o Studio. + +O contrato nao deve incluir descoberta dinamica de plugins, reflection, classpath scanning ou carregamento externo de JARs. + +O registro inicial deve continuar explicito no composition root da aplicacao, com `prometeu-app/src/main/java/p/studio/AppContainer.java` como ponto preferencial de composicao. Codigo comum deve consumir o provider via `registry.require(languageId)` e nao deve instanciar diretamente classes PBS, incluindo `PBSFrontendPhaseService`. + +PBS permanece o unico provider inicial. Nenhum frontend real novo deve ser criado por esta frente. diff --git a/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md b/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md new file mode 100644 index 00000000..b9782807 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md @@ -0,0 +1,92 @@ +--- +id: DEC-0040 +ticket: multi-frontend-provider-contract +title: FrontendProvider explicito como contrato de frontend +status: accepted +created: 2026-07-15 +ref_agenda: AGD-0057 +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Context + +This decision belongs to domain owner `compiler/general`, with impact on `studio`. + +The repository already has `FrontendRegistryService`, `FrontendSpec`, `FrontendPhaseService`, and `languageId` based selection. Those surfaces are enough to keep PBS working, but common compiler and Studio code still has places where PBS-specific classes or assumptions can leak into composition and consumption paths. + +The multi-frontend direction requires a stable provider boundary before removing PBS-specific branches from common code. The boundary must make frontend registration explicit without turning the Studio or compiler into a dynamic plugin platform. + +This decision resolves `AGD-0057`. + +## Decision + +The repository MUST introduce an explicit `FrontendProvider` contract as the common frontend registration unit. + +`FrontendProvider` MUST expose the following minimum responsibilities: + +- `specification()`: returns the frontend specification, including its stable `languageId`; +- `compiler()`: returns the compiler-facing frontend service or phase equivalent used by the build pipeline; +- `languageService()`: returns an optional editor-facing language service capability for Studio consumers. + +`languageService()` MUST be optional. A frontend that can compile but does not provide editor services MUST remain a valid provider. + +`FrontendRegistryService` MUST resolve providers by `languageId`. The common consumption shape SHOULD become `provider = registry.require(languageId)` or an equivalent explicit lookup that fails clearly for unknown languages. + +PBS MUST be registered as the only initial real provider through a `PBSFrontendProvider` or equivalent concrete provider object. This work MUST NOT introduce another real frontend. + +Provider registration MUST remain explicit in the application composition root. `prometeu-app/src/main/java/p/studio/AppContainer.java` is the preferred initial composition point for registering the PBS provider. + +Common compiler, build pipeline, and Studio code MUST NOT instantiate PBS-specific frontend services directly. In particular, common code MUST NOT directly instantiate `PBSFrontendPhaseService`; it MUST obtain the relevant service through the provider resolved from the registry. + +This decision MUST NOT introduce dynamic plugin discovery, reflection-based discovery, classpath scanning, external JAR loading, or runtime plugin installation. + +## Rationale + +An explicit provider object gives the project one stable unit for frontend identity, compilation, and optional editorial capability. It keeps `languageId` as the selection key while avoiding scattered direct knowledge of PBS in common code. + +Keeping the provider small prevents a premature plugin architecture. The immediate goal is static multi-frontend readiness inside the repository, not external extensibility. + +Making language services optional separates build correctness from Studio editor assistance. A frontend should be able to participate in compilation without being forced to implement editor features in the same wave. + +Using the application composition root for registration keeps ownership clear: composition may know that PBS exists, but shared compiler and Studio consumers should only know the provider contract. + +## Implications + +- `FrontendRegistryService` will need to evolve from spec/phase lookups into provider lookup, while preserving compatibility during migration where necessary. +- Existing PBS registration must be wrapped behind a provider object. +- Common consumers that currently request `FrontendSpec` or `FrontendPhaseService` directly may be migrated incrementally to provider lookup. +- Studio catalog code may continue listing specifications, but its source should become provider-derived rather than PBS-specific. +- Build pipeline code should obtain compiler-facing frontend behavior from the resolved provider. +- Error handling for unknown `languageId` must remain explicit and diagnostic-friendly. +- No product or runtime behavior should change for PBS as the only registered provider. + +## Propagation Targets + +- specs: + - Add or update a `compiler/general` specification for the frontend provider and registry contract. + - Reference Studio-facing optional language service capability where relevant. +- plans: + - Create an implementation plan for provider contract introduction, PBS provider registration, consumer migration, and tests. +- code: + - `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` + - PBS frontend module provider implementation. + - `prometeu-compiler/prometeu-build-pipeline/...` consumers that resolve frontend services. + - `prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java` + - `prometeu-app/src/main/java/p/studio/AppContainer.java` +- tests: + - Registry resolves a provider by `languageId`. + - PBS is registered as the only initial real provider. + - Unknown `languageId` fails with a clear error. + - Common code can obtain compiler-facing frontend behavior without directly instantiating `PBSFrontendPhaseService`. +- docs: + - Decision-derived implementation plan. + - Lessons after implementation and housekeeping, if the completed work produces reusable guidance. + +## References + +- Agenda: AGD-0057 +- Source discussion: DSC-0054 + +## Revision Log + +- 2026-07-15: Initial decision drafted from accepted `AGD-0057`. diff --git a/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md b/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md new file mode 100644 index 00000000..ec791081 --- /dev/null +++ b/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md @@ -0,0 +1,71 @@ +--- +id: PLN-0103 +ticket: multi-frontend-provider-contract +title: Specify frontend provider and registry contract +status: open +created: 2026-07-15 +ref_decisions: [DEC-0040] +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Briefing + +DEC-0040 locks an explicit `FrontendProvider` contract as the common frontend registration unit. The first implementation step is to make that contract normative in the compiler/general specs before changing code. + +Domain owner: `compiler/general`, with impact on `studio`. + +## Objective + +Specify the frontend provider and registry contract so implementation can introduce the API without relying on implicit behavior or PBS-specific assumptions. + +## Dependencies + +- Accepted decision: `DEC-0040`. +- Existing compiler specs under `docs/specs/compiler/`. +- Existing Studio/editor references may be linked but must not become the owner of the contract. + +## Scope + +- Add or update a compiler/general spec section defining `FrontendProvider`. +- Define required provider responsibilities: + - `specification()`; + - `compiler()`; + - optional `languageService()`. +- Define `languageId` as the registry lookup key. +- Define explicit provider registration as the only supported v1 registration model. +- Define PBS as the only initial real provider. +- Define unknown-language failure behavior as explicit and diagnostic-friendly. +- Define that common code must obtain compiler-facing frontend behavior through provider lookup. + +## Non-Goals + +- Do not specify dynamic plugin discovery. +- Do not specify reflection, classpath scanning, external JAR loading, or runtime plugin installation. +- Do not introduce a second real frontend. +- Do not define the full Studio language-service API beyond optional provider capability. + +## Execution Method + +1. Inspect existing compiler/general spec organization and choose the nearest owner document for registry and frontend composition. +2. Add a `FrontendProvider` section with normative `MUST` language for required and optional responsibilities. +3. Add a registry section stating that providers are resolved by `languageId` and that unknown languages fail clearly. +4. Add a registration section stating that provider registration is explicit and composition-root-owned. +5. Add a PBS v1 section stating that PBS is the only initial real provider and no new frontend is introduced by this work. +6. Cross-reference Studio only as an optional language-service consumer, not as the owner of the provider contract. + +## Acceptance Criteria + +- A compiler/general spec defines `FrontendProvider`, registry lookup, explicit registration, and PBS-only initial provider status. +- The spec prohibits plugin discovery, reflection discovery, scanning, external JAR loading, and runtime plugin installation for this decision. +- The spec makes `languageService()` optional and does not require editor support for a compilable frontend. +- The spec is written in English. + +## Tests + +- Documentation validation through review against `DEC-0040`. +- No code tests are required in this plan. + +## Affected Artifacts + +- `docs/specs/compiler/...` +- `discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md` diff --git a/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md b/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md new file mode 100644 index 00000000..9f6b6265 --- /dev/null +++ b/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md @@ -0,0 +1,69 @@ +--- +id: PLN-0104 +ticket: multi-frontend-provider-contract +title: Introduce FrontendProvider registry API +status: open +created: 2026-07-15 +ref_decisions: [DEC-0040] +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Briefing + +DEC-0040 requires common code to resolve frontend behavior through a provider. This plan introduces the API surface in the frontend registry without forcing all consumers to migrate in the same change. + +Domain owner: `compiler/general`. + +## Objective + +Introduce `FrontendProvider` and provider-based registry lookup while preserving existing PBS behavior during migration. + +## Dependencies + +- `PLN-0103` should define the normative spec first. +- Accepted decision: `DEC-0040`. +- Existing registry module: `prometeu-compiler/prometeu-frontend-registry`. + +## Scope + +- Add the `FrontendProvider` contract in the frontend registry module. +- Add an optional language-service return shape, using an existing interface if one already exists or a minimal neutral placeholder only if required. +- Add provider registration and provider lookup by `languageId`. +- Add `require(languageId)` or equivalent explicit lookup that fails clearly for unknown languages. +- Preserve compatibility methods during migration if existing consumers still call spec or phase lookup. + +## Non-Goals + +- Do not register PBS in this plan unless needed for API tests with a simple fixture. +- Do not migrate build pipeline or Studio consumers in this plan. +- Do not add plugin discovery, reflection, scanning, external JAR loading, or runtime plugin installation. +- Do not define a broad editor API. + +## Execution Method + +1. Inspect `FrontendRegistryService`, `FrontendSpec`, and `FrontendPhaseService` to confirm current method names and package ownership. +2. Add `FrontendProvider` to the registry-facing package with `specification()`, `compiler()`, and optional `languageService()`. +3. Update `FrontendRegistryService` so its primary storage is provider keyed by `languageId`. +4. Add `require(languageId)` or the nearest local naming equivalent for provider lookup. +5. Keep old spec/phase accessor methods as provider-derived compatibility wrappers if they are still used. +6. Add registry unit tests for provider registration, provider lookup, duplicate language handling if currently supported, and unknown-language errors. + +## Acceptance Criteria + +- `FrontendProvider` exists and exposes all responsibilities required by `DEC-0040`. +- `FrontendRegistryService` can resolve a provider by `languageId`. +- Unknown `languageId` lookup fails with a clear exception or diagnostic message. +- Existing callers can still compile until their migration plan runs. + +## Tests + +- Registry test: registered provider is returned by `languageId`. +- Registry test: unknown `languageId` fails clearly. +- Registry test: provider-derived spec listing remains correct if compatibility methods remain. +- Run the relevant Gradle test task for `prometeu-frontend-registry`. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` +- New `FrontendProvider` contract in the same registry API surface. +- Registry tests under `prometeu-compiler/prometeu-frontend-registry/src/test/...` diff --git a/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md b/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md new file mode 100644 index 00000000..fbeef9ba --- /dev/null +++ b/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md @@ -0,0 +1,73 @@ +--- +id: PLN-0105 +ticket: multi-frontend-provider-contract +title: Wrap PBS frontend as explicit provider +status: open +created: 2026-07-15 +ref_decisions: [DEC-0040] +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Briefing + +DEC-0040 requires PBS to become the only initial real provider behind the new `FrontendProvider` contract. This plan wraps existing PBS frontend behavior without changing PBS product behavior. + +Domain owner: `compiler/general`, with implementation in `compiler/pbs` and composition impact in `prometeu-app`. + +## Objective + +Create and register an explicit PBS provider through the application composition root. + +## Dependencies + +- `PLN-0104` must introduce `FrontendProvider` and provider lookup first. +- Accepted decision: `DEC-0040`. +- Existing PBS frontend phase/service implementation. +- Application composition root in `prometeu-app`. + +## Scope + +- Add `PBSFrontendProvider` or equivalent concrete provider object. +- Make the provider return the existing PBS `FrontendSpec`. +- Make the provider return the existing PBS compiler-facing service or phase. +- Return no language service, or the existing PBS language-service adapter only if already present and compatible. +- Register PBS explicitly in `prometeu-app/src/main/java/p/studio/AppContainer.java` or the nearest current application composition point. +- Ensure PBS remains the only initial real provider. + +## Non-Goals + +- Do not create another real frontend. +- Do not change PBS parsing, semantics, lowering, or runtime output. +- Do not migrate all common consumers in this plan. +- Do not introduce dynamic provider discovery. + +## Execution Method + +1. Inspect PBS frontend module boundaries and locate the current `FrontendSpec` and `FrontendPhaseService` construction. +2. Add `PBSFrontendProvider` in the PBS frontend module or an existing integration package that can legally depend on PBS. +3. Implement `specification()` and `compiler()` by delegating to the existing PBS objects. +4. Implement `languageService()` as empty unless a current Studio-compatible PBS language service already exists. +5. Update `AppContainer` or the existing composition root to register the PBS provider explicitly with `FrontendRegistryService`. +6. Remove direct PBS registration paths that duplicate the provider registration if they become redundant. +7. Add tests proving only PBS is registered as the real provider in the default composition path. + +## Acceptance Criteria + +- PBS is represented by a concrete provider object. +- Default application composition registers PBS explicitly as a provider. +- PBS remains functional through existing compile/build flows. +- No additional real frontend is introduced. +- No dynamic discovery mechanism is added. + +## Tests + +- Provider test: `PBSFrontendProvider.specification()` returns the PBS language id. +- Provider test: `PBSFrontendProvider.compiler()` returns working compiler-facing behavior. +- Composition test: default registry contains PBS as the only real provider. +- Existing PBS compile/build tests continue to pass. + +## Affected Artifacts + +- PBS frontend module under `prometeu-compiler/frontends/prometeu-frontend-pbs/...` +- `prometeu-app/src/main/java/p/studio/AppContainer.java` +- Registry or application composition tests. diff --git a/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md b/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md new file mode 100644 index 00000000..1dd6090f --- /dev/null +++ b/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md @@ -0,0 +1,74 @@ +--- +id: PLN-0106 +ticket: multi-frontend-provider-contract +title: Migrate common consumers to provider lookup +status: open +created: 2026-07-15 +ref_decisions: [DEC-0040] +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Briefing + +DEC-0040 forbids common compiler, build pipeline, and Studio code from directly instantiating PBS-specific frontend services. After the registry API and PBS provider exist, consumers must move to provider lookup. + +Domain owner: `compiler/general`, with impact on `studio`. + +## Objective + +Migrate common consumers from direct spec/phase/PBS access to provider-based lookup by `languageId`. + +## Dependencies + +- `PLN-0104` must provide provider lookup. +- `PLN-0105` must register PBS as a provider. +- Accepted decision: `DEC-0040`. + +## Scope + +- Audit common compiler, build pipeline, Studio, and app code for direct PBS frontend service construction. +- Replace common code service lookup with provider lookup. +- Make build pipeline frontend execution obtain compiler-facing behavior from `provider.compiler()`. +- Make Studio project language catalog list specifications from providers. +- Keep PBS-specific construction inside PBS provider or composition root only. +- Add or update tests that prove common code does not directly instantiate `PBSFrontendPhaseService`. + +## Non-Goals + +- Do not remove compatibility registry APIs unless all callers have migrated and the removal is local. +- Do not introduce new frontend behavior. +- Do not change backend IR, validation boundaries, or lifecycle semantics beyond provider lookup. +- Do not implement optional Studio language services that do not already exist. + +## Execution Method + +1. Search for `PBSFrontendPhaseService`, PBS frontend constructors, `getFrontendPhaseService`, and `getFrontendSpec` usage outside PBS and composition-owned code. +2. Classify each usage as composition-owned, PBS-owned, or common consumer. +3. Update common consumers to resolve `FrontendProvider` by `languageId`. +4. Update `FrontendPhasePipelineStage` so it calls provider compiler behavior rather than direct phase lookup. +5. Update `ProjectLanguageCatalogService` so its catalog is provider-derived. +6. Keep compatibility wrappers only where they reduce migration risk and are provider-derived. +7. Add architectural tests or focused unit tests that fail if common modules instantiate `PBSFrontendPhaseService` directly. +8. Run relevant compiler, build pipeline, Studio, and app tests. + +## Acceptance Criteria + +- Common compiler/build pipeline/Studio code obtains frontend behavior through provider lookup. +- Direct `PBSFrontendPhaseService` instantiation remains only in PBS provider or approved composition code. +- `ProjectLanguageCatalogService` is provider-derived. +- Unknown `languageId` failures remain clear after consumer migration. +- PBS compile/build behavior remains unchanged. + +## Tests + +- Unit or integration test: build pipeline resolves PBS through provider and compiles an existing PBS fixture. +- Unit test: Studio language catalog lists PBS from provider specs. +- Architecture test or grep-backed test: common modules do not instantiate `PBSFrontendPhaseService`. +- Existing PBS and build pipeline tests pass. + +## Affected Artifacts + +- `prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java` +- `prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java` +- Common code currently using `FrontendRegistryService.getFrontendSpec` or `getFrontendPhaseService`. +- Tests in compiler, build pipeline, Studio, and app modules. diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index a120673e..6b0c9b03 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -14,13 +14,13 @@ "last_modified" : 1779659315450, "fingerprint" : "ac565160c0dceb321b8f6c9094f2b5e6ae398396fe32c8ead706f5cc36f465cf", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 673720574, -523190018, -117903106, 945858814, -1600620290, 1484833022 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgICAgICAQAAAAAAAAAAAAABAQEAAAAAAAAAAAAAAAEDBAQEBAQCAQAAAAAAAQEBAQICAgEAAAAAAAAAAAAAAQMEAgUFBQQCAQEBAQECAgICBAQEAgEAAAAAAAAAAAABAwQCBQUFBQQDAwMDAgQEBAQFAgIEAwEBAAAAAAAAAAEDBAIFBQUFAgQEBgYEBQUFBQICAgIEAwMBAQAAAAAAAQMEAgUFBQICAgMDAwIFBQUFBQICAgIGBgMCAQAAAAABAwQCBQUFAgICAgMDAgUFBQUFAgICAwMDBAQCAQEAAAEDBAIFBQUCAgICAwMCBQUFBQUCAgICAwMCAgQFAQAAAQMEAgUFBQICAgIDAwIFBQUFBAQEBAQDAwQEBQEAAAABAwQCBQUFAgICAgMDAgUFBAQFAgICAgYGAgUBAAAAAAEDBAIEBAQEBAICAwMCBQQFBQEBAQEBAwMBAQAAAAAAAQMEBAUFBQUCBAIDAwIEBQEBAAAAAAABAQAAAAAAAAABAwICBQEBAQECBAYGBAUBAAAAAAAAAAAAAAAAAAAAAQECAgIBAAAAAAEDAwICAQAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 673720574, -523190018, -117903106, 945858814, -1600620290, 1484833022 ] } }, "diagnostics" : [ ] @@ -59,13 +59,13 @@ "last_modified" : 1779659315452, "fingerprint" : "6dd024eb2259efaa03908ff0c3b75eb67f9da56d365e4a35d8e619b71c7507db", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 255, -540033025, -134746113, -101191169, 945858815, 1501544959, -1617463297, -1583777281, -1583908353, -1617462785, 929015807, 962701823, 690432511 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBAAAAAAAAAAAAAAABAQAAAAAAAAAAAAECBQYGBAIHBwgBAAAAAAAAAAEBAQICAQEAAAAAAAAAAQIFAwMGBQUFBQIBAAAAAAEBCQIHBQUDBAEBAAAAAAABAgUDAwIICAoIBQIBAQEBBwcLCwwIAgYGAwMBAAAAAAECBQMDAgoKCgoKBQMDAwIFBQgCCgIKAgIGAwEAAAAAAQIFAwMCCAgICAgCBQYGBQoKCgoCCgICAwMGAwEAAAABAgUDAggICAgICAICAwMCCAgIAggFBQUGBgYDDQAAAAECBgMCCAgICAgIAgIDAggICAgFBQoCAwMDAwQEAQAAAQIGAwIICAgICAgCAgMCCAgIBQgKAQEBAQEBAQQBAAABAgYDAggICAgIAgICAwIKCAUIAQEAAAAAAAAAAQEAAAECBgMCCAgICAUFAgIDAggFCgEAAAAAAAAAAAAAAAAAAQIGAwIICAUFCAIFBQYLBQgBAAAAAAAAAAAAAAAAAAABAgYFBQUFCAoBAQIDBAIJAQAAAAAAAAAAAAAAAAAAAQECAwIICAgBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 255, -540033025, -134746113, -101191169, 945858815, 1501544959, -1617463297, -1583777281, -1583908353, -1617462785, 929015807, 962701823, 690432511 ] } }, "diagnostics" : [ ] @@ -76,13 +76,13 @@ "last_modified" : 1779659315453, "fingerprint" : "c8e30f40473deedb265be26967f6bf5f2ba35a2bd5d0a049dcb8843fa60d5600", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -93,13 +93,13 @@ "last_modified" : 1779659315454, "fingerprint" : "58a6a9bc02d9174fdc6bcd6f71f5fb86c47d506812e83cae5b0e23a1f951dbbf", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -110,13 +110,13 @@ "last_modified" : 1779659315454, "fingerprint" : "110c4f835a40bb370c7bb7761afcd69de0d38e75798d20d50f4c203aa56f213a", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -127,13 +127,13 @@ "last_modified" : 1779659315455, "fingerprint" : "2e6fb2cfbf77f4b3c0d116b9b77a3ae228cdc5671bd18320285824faef9674d3", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -144,13 +144,13 @@ "last_modified" : 1779659315455, "fingerprint" : "c8e30f40473deedb265be26967f6bf5f2ba35a2bd5d0a049dcb8843fa60d5600", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -161,13 +161,13 @@ "last_modified" : 1779659315456, "fingerprint" : "94ac699b5e913925cf881e76ff951875147b598b1ee9870187111e7ca0b40d1d", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239 ] } }, "diagnostics" : [ ] @@ -178,13 +178,13 @@ "last_modified" : 1779659315457, "fingerprint" : "fc0a623650619ca39c1ce2f9f9e1b0f6951abd194e18ea60c682fae6a769df97", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -195,13 +195,13 @@ "last_modified" : 1779659315457, "fingerprint" : "7ada8efefcd6d069b10846fefb9bd9cff1a1fa4c1565bbebfd68fc83645f0732", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -250,13 +250,13 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711 ] } }, "diagnostics" : [ ] @@ -267,13 +267,13 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 1081622783, 677921023, 676868351, 673720575, -2005909249, -1466932993, 1615868159 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAAAAAAAAAEBAQABAQEBAQEBAQIDBAQEBAMCAwQFBQUFBAIDBAUFBgYHAgMEBwUFBwcAAgQEBwcHBg==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 1081622783, 677921023, 676868351, 673720575, -2005909249, -1466932993, 1615868159 ] } }, "diagnostics" : [ ] @@ -284,13 +284,13 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { - "palette" : { - "rgba8888" : [ 1081622783, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAABAgIAAAAAAQIDBAAAAAECAwQEAAECAgMDAwMCAgUEBAQEBAMFBAQFBQUFBAQEBQUEBAQEBQUFBAQFBQ==" + }, + "palette" : { + "rgba8888" : [ 1081622783, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] } }, "diagnostics" : [ ] @@ -301,13 +301,13 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 676868351, 1081622783, -1466932993, 1615868159, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgICAgIDBAABAgICAgMDBAABAgICBAQEBAAAAQIDAwMDAwUAAAUFBQUDAwUEAwMDBQUDAwMFBQMDBQUFAw==" + }, + "palette" : { + "rgba8888" : [ 673720575, 676868351, 1081622783, -1466932993, 1615868159, -2005909249 ] } }, "diagnostics" : [ ] @@ -318,13 +318,13 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 1081622783, 676868351, 673720575, 677921023, -2005909249, 1615868159, -1466932993 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAABAQEAAAAAAAEBAQEBAQEAAgMDAwMCBAEDBQUFBQMCBAYHBwUFAwIEBgYFBQYDAgQHBgYGAwMEAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 1081622783, 676868351, 673720575, 677921023, -2005909249, 1615868159, -1466932993 ] } }, "diagnostics" : [ ] @@ -335,13 +335,13 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 677921023, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAwMEBQUAAAECAwUFBgAAAAIDBQYGAAAAAwMFBgYAAAMEAwUGBgADBgQDBQYGAwYFBAMFBgYDBgUEAwUGBg==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 677921023, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] } }, "diagnostics" : [ ] @@ -352,13 +352,13 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgIAAAAAAQEAAgIAAQEBAAAAAgIBAQEAAAECAwIBAQAAAQIDAwEBAAABAgMDAQEAAAECAwIBAQEAAgMCAQ==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -369,13 +369,13 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, 1615868159, -1466932993, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQECAAACAAEBAAICAAIBAQAAAAICAQMBAgAAAgIDAwECAAACAgMDAQIAAAICAQMBAgAAAgICAQMBAAICAg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, 1615868159, -1466932993, 673720575 ] } }, "diagnostics" : [ ] @@ -386,13 +386,13 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { - "palette" : { - "rgba8888" : [ -1466932993, 1615868159, 673720575, 676868351, 677921023, 1217939711, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgIDBAUGAAACAwQFBQYGAAIDBQUFBgYAAgIFBQUGBgACAQIFBQYGAAIBBgIFBgYAAgEABgIGBgACAQAGAg==" + }, + "palette" : { + "rgba8888" : [ -1466932993, 1615868159, 673720575, 676868351, 677921023, 1217939711, -2005909249 ] } }, "diagnostics" : [ ] @@ -403,13 +403,13 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 1615868159, -2005909249, -1466932993, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAQEAAwIEAAABAQADAwQFBAABAQADBgUEBAABAAAGBgUFBAAAAQYGBgUEAAICBgYGBgAAAgIGBgYEAAEBAg==" + }, + "palette" : { + "rgba8888" : [ 673720575, 1615868159, -2005909249, -1466932993, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -420,13 +420,13 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAEBAgIAAAEAAAICAQEAAAEAAAAAAQEAAQEBAQAAAQEDAgIBAQAAAAIDAgIBAQAAAAIDAgICAQEAAgIDAgICAg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -437,13 +437,13 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { - "palette" : { - "rgba8888" : [ -1466932993, -2005909249, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAEBAgIAAAEBAQAAAgIBAQEAAAEBAQEAAAABAQAAAAABAQEAAAICAwEBAAACAgMCAAACAgIDAgECAgICAwICAQ==" + }, + "palette" : { + "rgba8888" : [ -1466932993, -2005909249, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -454,13 +454,13 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 673720575, 1615868159, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAwMAAwIBAQIDAwICBAECAwMCBAUEAgIDAgQEBQYDAgIEBQUGBgAAAgQFBgYGAAACAgYGBgYAAwMCBAYGBg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 673720575, 1615868159, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -471,13 +471,13 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 673720575, -2005909249, 1615868159, 676868351, 677921023 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQICAwMAAAECAgICAwAAAQICAgIDAAABAgIDAQMAAAEDAQQEAQAABAQFBAUEAAAAAAAFAAUAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 673720575, -2005909249, 1615868159, 676868351, 677921023 ] } }, "diagnostics" : [ ] @@ -488,13 +488,13 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { - "palette" : { - "rgba8888" : [ 1615868159, 673720575, 676868351, -2005909249, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQAAAQEBAAEBAAEAAAEBAgEBAAADAQICAgEAAAMCAgQCAgEAAAQEBQQEAQADBQUFBQUCAQAFBQUFBQUCAQ==" + }, + "palette" : { + "rgba8888" : [ 1615868159, 673720575, 676868351, -2005909249, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -505,13 +505,13 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 1615868159, -2005909249, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAQABAQEBAQABAAABAAIBAQAAAwAAAgEBAAMDAwABAQADAwQDAwIBAAQEBQQEAQADBQUFBQUAAwUFBQUFBQ==" + }, + "palette" : { + "rgba8888" : [ 673720575, 1615868159, -2005909249, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -522,13 +522,13 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { - "palette" : { - "rgba8888" : [ 1615868159, -2005909249, 673720575, 1217939711, 676868351, 677921023 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAQIDAwMAAQEBAQIDAwABAQEBAgMDAAIAAQECAwMCBAQCAAIDAwQFBAUEBAMDBQMFAwMDAwMDAwMDAwMDAw==" + }, + "palette" : { + "rgba8888" : [ 1615868159, -2005909249, 673720575, 1217939711, 676868351, 677921023 ] } }, "diagnostics" : [ ] -- 2.47.2 From f8b9c5b27d775ac4d5c266ccf8e46a81a290f743 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:26:37 +0100 Subject: [PATCH 2/6] implements PLN-0103 --- discussion/index.ndjson | 2 +- ...frontend-provider-and-registry-contract.md | 2 +- ...ler Pipeline Entry Points Specification.md | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 1bd164a4..25d5f783 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -10,7 +10,7 @@ {"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-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md b/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md index ec791081..e16d4b3c 100644 --- a/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md +++ b/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md @@ -2,7 +2,7 @@ id: PLN-0103 ticket: multi-frontend-provider-contract title: Specify frontend provider and registry contract -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0040] tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] 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 01936e51..a63c4e0d 100644 --- a/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md +++ b/docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md @@ -14,6 +14,7 @@ Its purpose is to make the compiler usable through explicit entrypoints instead This document defines: - the canonical stage order shared by compiler entrypoints, +- the frontend provider and registry boundary used by shared compiler composition, - the terminal stage and mandatory behavior of `analyze`, - the terminal stage and mandatory behavior of `compile`, - the terminal stage and mandatory behavior of `build`, @@ -25,6 +26,7 @@ This document does not define: - one mandatory Java class or package layout, - editor-specific source providers or document-session providers, - frontend-specific semantic facts beyond the minimum shared `AnalysisSnapshot` contract, +- dynamic frontend plugin discovery, - or one mandatory CLI architecture. ## 3. Authority and Precedence @@ -229,6 +231,26 @@ This authority model MUST NOT: 2. move semantic inline hint policy into LSP, 3. or imply that the host editor may synthesize semantic hints when the frontend did not publish them. +## 8.3 Frontend Provider and Registry Contract + +The shared compiler composition surface MUST represent each registered frontend through a `FrontendProvider` or equivalent provider contract. + +At minimum, each provider MUST expose: + +1. `specification()`, returning the frontend-owned static contract, including its stable `languageId`; +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. + +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. + +Common compiler, build pipeline, and Studio-facing consumers MUST obtain frontend behavior through provider lookup. They MUST NOT directly instantiate frontend-specific compiler services, except inside the frontend provider itself or inside an approved application composition root. + +Provider registration MUST be explicit in v1. The registry contract MUST NOT use dynamic plugin discovery, reflection-based discovery, classpath scanning, external JAR loading, or runtime plugin installation to discover frontends. + +PBS is the only initial real provider for this contract. PBS MAY be registered by an application composition root, but PBS MUST NOT become an exclusive semantic owner of the shared compiler pipeline. + ## 9. Public Surface Rule The shared compiler public surface MUST expose explicit entrypoints equivalent in meaning to: -- 2.47.2 From 66c1b1a0338bdbf794e0a52d6ca53ee140a43e90 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:28:30 +0100 Subject: [PATCH 3/6] implements PLN-0104 --- discussion/index.ndjson | 2 +- ...introduce-frontendprovider-registry-api.md | 2 +- .../prometeu-frontend-api/build.gradle.kts | 4 +- .../services/FrontendLanguageService.java | 7 +++ .../compiler/services/FrontendProvider.java | 15 ++++++ .../compiler/FrontendRegistryService.java | 49 ++++++++++++++++--- .../compiler/FrontendRegistryServiceTest.java | 36 ++++++++++++++ 7 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java create mode 100644 prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java create mode 100644 prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 25d5f783..9d6da8a1 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -10,7 +10,7 @@ {"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-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md b/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md index 9f6b6265..c0a65a12 100644 --- a/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md +++ b/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md @@ -2,7 +2,7 @@ id: PLN-0104 ticket: multi-frontend-provider-contract title: Introduce FrontendProvider registry API -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0040] tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] diff --git a/prometeu-compiler/prometeu-frontend-api/build.gradle.kts b/prometeu-compiler/prometeu-frontend-api/build.gradle.kts index 0bea0481..06c18c58 100644 --- a/prometeu-compiler/prometeu-frontend-api/build.gradle.kts +++ b/prometeu-compiler/prometeu-frontend-api/build.gradle.kts @@ -5,5 +5,5 @@ plugins { dependencies { api(project(":prometeu-infra")) - implementation(project(":prometeu-compiler:prometeu-compiler-core")) -} \ No newline at end of file + api(project(":prometeu-compiler:prometeu-compiler-core")) +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java new file mode 100644 index 00000000..529d8cac --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java @@ -0,0 +1,7 @@ +package p.studio.compiler.services; + +/** + * Marker contract for optional frontend-owned editor services. + */ +public interface FrontendLanguageService { +} diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java new file mode 100644 index 00000000..339c96be --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java @@ -0,0 +1,15 @@ +package p.studio.compiler.services; + +import p.studio.compiler.models.FrontendSpec; + +import java.util.Optional; + +public interface FrontendProvider { + FrontendSpec specification(); + + FrontendPhaseService compiler(); + + default Optional languageService() { + return Optional.empty(); + } +} diff --git a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java index 3c84d122..0c440e7b 100644 --- a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java +++ b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java @@ -2,6 +2,7 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSpec; import p.studio.compiler.services.FrontendPhaseService; +import p.studio.compiler.services.FrontendProvider; import p.studio.compiler.services.PBSFrontendPhaseService; import java.util.HashMap; @@ -10,29 +11,61 @@ import java.util.Map; import java.util.Optional; public class FrontendRegistryService { - private static final Map FRONTEND_SPECS = new HashMap<>(); - private static final Map FRONTEND_PHASE_SERVICES = new HashMap<>(); + private static final Map FRONTEND_PROVIDERS = new HashMap<>(); static { - FRONTEND_SPECS.put(PBSDefinitions.PBS.getLanguageId(), PBSDefinitions.PBS); - FRONTEND_PHASE_SERVICES.put(PBSDefinitions.PBS.getLanguageId(), new PBSFrontendPhaseService()); + register(new StaticFrontendProvider(PBSDefinitions.PBS, new PBSFrontendPhaseService())); } public static FrontendSpec getDefaultFrontendSpec() { - return FRONTEND_SPECS.get(PBSDefinitions.PBS.getLanguageId()); + return require(PBSDefinitions.PBS.getLanguageId()).specification(); } public static Optional getFrontendSpec(final String languageId) { - return Optional.ofNullable(FRONTEND_SPECS.get(languageId)); + return getProvider(languageId).map(FrontendProvider::specification); } public static Optional getFrontendPhaseService(final String languageId) { - return Optional.ofNullable(FRONTEND_PHASE_SERVICES.get(languageId)); + return getProvider(languageId).map(FrontendProvider::compiler); + } + + public static Optional getProvider(final String languageId) { + return Optional.ofNullable(FRONTEND_PROVIDERS.get(languageId)); + } + + public static FrontendProvider require(final String languageId) { + final var provider = FRONTEND_PROVIDERS.get(languageId); + if (provider == null) { + throw new IllegalArgumentException("Unknown frontend languageId: " + languageId); + } + + return provider; } public static List listFrontendSpecs() { - return FRONTEND_SPECS.values().stream() + return FRONTEND_PROVIDERS.values().stream() + .map(FrontendProvider::specification) .sorted((left, right) -> left.getLanguageId().compareToIgnoreCase(right.getLanguageId())) .toList(); } + + public static List listProviders() { + return FRONTEND_PROVIDERS.values().stream() + .sorted((left, right) -> left.specification().getLanguageId().compareToIgnoreCase(right.specification().getLanguageId())) + .toList(); + } + + static void register(final FrontendProvider provider) { + final var languageId = provider.specification().getLanguageId(); + if (FRONTEND_PROVIDERS.containsKey(languageId)) { + throw new IllegalArgumentException("Duplicate frontend languageId: " + languageId); + } + + FRONTEND_PROVIDERS.put(languageId, provider); + } + + private record StaticFrontendProvider( + FrontendSpec specification, + FrontendPhaseService compiler) implements FrontendProvider { + } } diff --git a/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java b/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java new file mode 100644 index 00000000..6f2e7919 --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java @@ -0,0 +1,36 @@ +package p.studio.compiler; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class FrontendRegistryServiceTest { + + @Test + void requireShouldResolveProviderByLanguageId() { + final var provider = FrontendRegistryService.require(PBSDefinitions.PBS.getLanguageId()); + + assertEquals(PBSDefinitions.PBS.getLanguageId(), provider.specification().getLanguageId()); + assertSame(PBSDefinitions.PBS, provider.specification()); + } + + @Test + void requireShouldFailClearlyForUnknownLanguageId() { + final var thrown = assertThrows( + IllegalArgumentException.class, + () -> FrontendRegistryService.require("unknown-language")); + + assertTrue(thrown.getMessage().contains("unknown-language")); + } + + @Test + void specListingShouldBeProviderDerived() { + final var specs = FrontendRegistryService.listFrontendSpecs(); + + assertEquals(1, specs.size()); + assertEquals(PBSDefinitions.PBS.getLanguageId(), specs.getFirst().getLanguageId()); + } +} -- 2.47.2 From ba3af3c01b5e202397ecdf43b132f10cfdf848ef Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:29:51 +0100 Subject: [PATCH 4/6] implements PLN-0105 --- discussion/index.ndjson | 2 +- ...-wrap-pbs-frontend-as-explicit-provider.md | 2 +- prometeu-app/build.gradle.kts | 2 ++ .../src/main/java/p/studio/AppContainer.java | 2 ++ .../studio/compiler/PBSFrontendProvider.java | 28 +++++++++++++++++++ .../compiler/PBSFrontendProviderTest.java | 20 +++++++++++++ .../compiler/FrontendRegistryService.java | 12 ++++---- 7 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 9d6da8a1..49dfec69 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -10,7 +10,7 @@ {"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-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md b/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md index fbeef9ba..2d2b024b 100644 --- a/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md +++ b/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md @@ -2,7 +2,7 @@ id: PLN-0105 ticket: multi-frontend-provider-contract title: Wrap PBS frontend as explicit provider -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0040] tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] diff --git a/prometeu-app/build.gradle.kts b/prometeu-app/build.gradle.kts index 92e953ee..bbfcdfce 100644 --- a/prometeu-app/build.gradle.kts +++ b/prometeu-app/build.gradle.kts @@ -7,6 +7,8 @@ dependencies { implementation(project(":prometeu-infra")) implementation(project(":prometeu-lsp:prometeu-lsp-api")) implementation(project(":prometeu-lsp:prometeu-lsp-v1")) + implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) + implementation(project(":prometeu-compiler:prometeu-frontend-registry")) implementation(project(":prometeu-packer:prometeu-packer-api")) implementation(project(":prometeu-packer:prometeu-packer-v1")) implementation(project(":prometeu-studio")) diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index 9b1851c5..a73d0b74 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -2,6 +2,7 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; import p.packer.Packer; +import p.studio.compiler.FrontendRegistryService; import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; @@ -24,6 +25,7 @@ public final class AppContainer implements Container { private final LspServerLifecycle lspServerLifecycle; public AppContainer() { + FrontendRegistryService.bootstrapDefaults(); this.i18nService = new I18nService(); this.themeService = new ThemeService(); this.studioEventBus = new StudioEventBus(); 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 new file mode 100644 index 00000000..db1a2c94 --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendProvider.java @@ -0,0 +1,28 @@ +package p.studio.compiler; + +import p.studio.compiler.models.FrontendSpec; +import p.studio.compiler.services.FrontendPhaseService; +import p.studio.compiler.services.FrontendProvider; +import p.studio.compiler.services.PBSFrontendPhaseService; + +public final class PBSFrontendProvider implements FrontendProvider { + private final FrontendPhaseService compiler; + + public PBSFrontendProvider() { + this(new PBSFrontendPhaseService()); + } + + PBSFrontendProvider(final FrontendPhaseService compiler) { + this.compiler = compiler; + } + + @Override + public FrontendSpec specification() { + return PBSDefinitions.PBS; + } + + @Override + public FrontendPhaseService compiler() { + return compiler; + } +} 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 new file mode 100644 index 00000000..06244fc6 --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/PBSFrontendProviderTest.java @@ -0,0 +1,20 @@ +package p.studio.compiler; + +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; + +class PBSFrontendProviderTest { + + @Test + void shouldExposePbsSpecificationAndCompiler() { + final var provider = new PBSFrontendProvider(); + + assertEquals(PBSDefinitions.PBS.getLanguageId(), provider.specification().getLanguageId()); + assertInstanceOf(PBSFrontendPhaseService.class, provider.compiler()); + assertFalse(provider.languageService().isPresent()); + } +} diff --git a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java index 0c440e7b..43190fef 100644 --- a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java +++ b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java @@ -3,7 +3,6 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSpec; import p.studio.compiler.services.FrontendPhaseService; import p.studio.compiler.services.FrontendProvider; -import p.studio.compiler.services.PBSFrontendPhaseService; import java.util.HashMap; import java.util.List; @@ -14,7 +13,11 @@ public class FrontendRegistryService { private static final Map FRONTEND_PROVIDERS = new HashMap<>(); static { - register(new StaticFrontendProvider(PBSDefinitions.PBS, new PBSFrontendPhaseService())); + bootstrapDefaults(); + } + + public static void bootstrapDefaults() { + registerIfAbsent(new PBSFrontendProvider()); } public static FrontendSpec getDefaultFrontendSpec() { @@ -64,8 +67,7 @@ public class FrontendRegistryService { FRONTEND_PROVIDERS.put(languageId, provider); } - private record StaticFrontendProvider( - FrontendSpec specification, - FrontendPhaseService compiler) implements FrontendProvider { + private static void registerIfAbsent(final FrontendProvider provider) { + FRONTEND_PROVIDERS.putIfAbsent(provider.specification().getLanguageId(), provider); } } -- 2.47.2 From 44f03f771bd3ccdbe254841eeca39a7cd12d3854 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:32:19 +0100 Subject: [PATCH 5/6] implements PLN-0106 --- discussion/index.ndjson | 2 +- ...ate-common-consumers-to-provider-lookup.md | 2 +- .../stages/FrontendPhasePipelineStage.java | 10 +--- .../specs/FrontendProviderBoundaryTest.java | 59 +++++++++++++++++++ .../utilities/PrometeuManifestUtils.java | 2 +- .../workspaces/phases/DiscoverPhase.java | 11 ++-- .../build.gradle.kts | 4 +- .../compiler/FrontendRegistryService.java | 6 +- .../compiler/FrontendRegistryServiceTest.java | 8 +++ .../ProjectLanguageCatalogService.java | 4 +- .../ProjectLanguageCatalogServiceTest.java | 18 ++++++ 11 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java create mode 100644 prometeu-studio/src/test/java/p/studio/projects/ProjectLanguageCatalogServiceTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 49dfec69..3494e7d9 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -10,7 +10,7 @@ {"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-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"lessons":[]} {"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md b/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md index 1dd6090f..a1400a7a 100644 --- a/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md +++ b/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md @@ -2,7 +2,7 @@ id: PLN-0106 ticket: multi-frontend-provider-contract title: Migrate common consumers to provider lookup -status: open +status: done created: 2026-07-15 ref_decisions: [DEC-0040] tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java index 7fb1a1a9..68c7f41e 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java @@ -17,13 +17,7 @@ public class FrontendPhasePipelineStage implements PipelineStage { @Override public BuildingIssueSink run(final BuilderPipelineContext ctx, final LogAggregator logs) { final var frontedSpec = ctx.resolvedWorkspace.frontendSpec(); - final var service = FrontendRegistryService.getFrontendPhaseService(frontedSpec.getLanguageId()); - if (service.isEmpty()) { - return BuildingIssueSink.empty() - .report(builder -> builder - .error(true) - .message("[BUILD]: unable to find a service for frontend phase: " + frontedSpec.getLanguageId())); - } + final var provider = FrontendRegistryService.require(frontedSpec.getLanguageId()); final var projectTable = ctx.resolvedWorkspace.graph().projectTable(); final var fileTable = ctx.fileTable; final var frontendPhaseContext = new FrontendPhaseContext( @@ -36,7 +30,7 @@ public class FrontendPhasePipelineStage implements PipelineStage { assetSurfaceContextLoader.load(ctx.resolvedWorkspace.mainProject().getRootPath())); final var diagnostics = DiagnosticSink.empty(); final var issues = BuildingIssueSink.empty(); - ctx.irBackend = service.get().compile(frontendPhaseContext, diagnostics, logs, issues); + ctx.irBackend = provider.compiler().compile(frontendPhaseContext, diagnostics, logs, issues); logs.using(log).debug("Frontend phase completed successfully!"); adaptDiagnostics(diagnostics, issues); return issues; 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 new file mode 100644 index 00000000..a69363d6 --- /dev/null +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java @@ -0,0 +1,59 @@ +package p.studio.compiler.specs; + +import org.junit.jupiter.api.Test; + +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.fail; + +class FrontendProviderBoundaryTest { + + @Test + void commonModulesMustNotInstantiatePbsFrontendPhaseServiceDirectly() throws IOException { + final var repoRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize()); + final var commonSourceRoots = List.of( + repoRoot.resolve("prometeu-compiler/prometeu-build-pipeline/src/main/java"), + repoRoot.resolve("prometeu-compiler/prometeu-deps/src/main/java"), + repoRoot.resolve("prometeu-studio/src/main/java"), + repoRoot.resolve("prometeu-app/src/main/java")); + + for (final var sourceRoot : commonSourceRoots) { + 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 PBSFrontendPhaseService(")) + .toList(); + if (!violations.isEmpty()) { + fail("common modules must resolve frontend compiler behavior through FrontendProvider: " + violations); + } + } + } + } + + private boolean contains(final Path path, final String needle) { + try { + return Files.readString(path).contains(needle); + } catch (IOException e) { + throw new IllegalStateException("failed to read " + path, e); + } + } + + private Path findRepoRoot(final Path start) { + var current = start; + while (current != null) { + if (Files.exists(current.resolve("settings.gradle.kts"))) { + return current; + } + current = current.getParent(); + } + fail("unable to locate repository root from " + start); + return start; + } +} diff --git a/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/utilities/PrometeuManifestUtils.java b/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/utilities/PrometeuManifestUtils.java index 8455d5c9..985d5f00 100644 --- a/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/utilities/PrometeuManifestUtils.java +++ b/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/utilities/PrometeuManifestUtils.java @@ -60,7 +60,7 @@ public final class PrometeuManifestUtils { .message("[DEPS]: invalid 'target' \"" + dto.target() + "\": " + manifestPathCanon)); } final var language = StringUtils.isBlank(dto.language()) - ? FrontendRegistryService.getDefaultFrontendSpec().getLanguageId() + ? FrontendRegistryService.getDefaultProvider().specification().getLanguageId() : dto.language(); final var dependencies = DependencyResolver.resolveDependencies(mainProjectRootPathCanon, dto.dependencies(), issuesLocal); if (ReadOnlyCollection.isNotEmpty(issuesLocal)) { diff --git a/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/workspaces/phases/DiscoverPhase.java b/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/workspaces/phases/DiscoverPhase.java index d4daea74..4b204b68 100644 --- a/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/workspaces/phases/DiscoverPhase.java +++ b/prometeu-compiler/prometeu-deps/src/main/java/p/studio/compiler/workspaces/phases/DiscoverPhase.java @@ -55,23 +55,24 @@ public class DiscoverPhase implements DependencyPhase { ctx.rootStdlib = manifest.get().stdlib(); ctx.target = manifest.get().target(); } - final var frontendSpec = FrontendRegistryService.getFrontendSpec(manifest.get().language()); + final var frontendProvider = FrontendRegistryService.getProvider(manifest.get().language()); // Returns empty when language is unknown - if (frontendSpec.isEmpty()) { + if (frontendProvider.isEmpty()) { issues.report(builder -> builder .error(true) .message("[DEPS]: unknown language " + manifest.get().language() + " for project " + manifest.get().name())); return Optional.empty(); } + final var frontendSpec = frontendProvider.get().specification(); // Enforces consistent language across projects if (Objects.isNull(ctx.frontendSpec)) { - ctx.frontendSpec = frontendSpec.get(); - } else if (!ctx.frontendSpec.getLanguageId().equals(frontendSpec.get().getLanguageId())) { + ctx.frontendSpec = frontendSpec; + } else if (!ctx.frontendSpec.getLanguageId().equals(frontendSpec.getLanguageId())) { // Reports language inconsistency across projects issues.report(builder -> builder .error(true) .message(String.format("[DEPS]: inconsistent language: [ %s ] has \"%s\" but should be \"%s\"", - manifest.get().name(), frontendSpec.get().getLanguageId(), ctx.frontendSpec.getLanguageId()))); + manifest.get().name(), frontendSpec.getLanguageId(), ctx.frontendSpec.getLanguageId()))); return Optional.empty(); } final var projectInfo = ProjectInfo diff --git a/prometeu-compiler/prometeu-frontend-registry/build.gradle.kts b/prometeu-compiler/prometeu-frontend-registry/build.gradle.kts index 7eff67cf..2caa4e92 100644 --- a/prometeu-compiler/prometeu-frontend-registry/build.gradle.kts +++ b/prometeu-compiler/prometeu-frontend-registry/build.gradle.kts @@ -6,7 +6,7 @@ dependencies { implementation(project(":prometeu-infra")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) - implementation(project(":prometeu-compiler:prometeu-frontend-api")) + api(project(":prometeu-compiler:prometeu-frontend-api")) implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) -} \ No newline at end of file +} diff --git a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java index 43190fef..bf30b6b3 100644 --- a/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java +++ b/prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java @@ -21,7 +21,11 @@ public class FrontendRegistryService { } public static FrontendSpec getDefaultFrontendSpec() { - return require(PBSDefinitions.PBS.getLanguageId()).specification(); + return getDefaultProvider().specification(); + } + + public static FrontendProvider getDefaultProvider() { + return require(PBSDefinitions.PBS.getLanguageId()); } public static Optional getFrontendSpec(final String languageId) { diff --git a/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java b/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java index 6f2e7919..71e5c32e 100644 --- a/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java +++ b/prometeu-compiler/prometeu-frontend-registry/src/test/java/p/studio/compiler/FrontendRegistryServiceTest.java @@ -33,4 +33,12 @@ class FrontendRegistryServiceTest { assertEquals(1, specs.size()); assertEquals(PBSDefinitions.PBS.getLanguageId(), specs.getFirst().getLanguageId()); } + + @Test + void providerListingShouldExposeOnlyPbsByDefault() { + final var providers = FrontendRegistryService.listProviders(); + + assertEquals(1, providers.size()); + assertEquals(PBSDefinitions.PBS.getLanguageId(), providers.getFirst().specification().getLanguageId()); + } } diff --git a/prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java b/prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java index 394e9cbb..fea4319d 100644 --- a/prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java +++ b/prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java @@ -9,8 +9,8 @@ import java.util.Objects; public final class ProjectLanguageCatalogService { public List listLanguageTemplates() { - return FrontendRegistryService.listFrontendSpecs().stream() - .map(this::toTemplate) + return FrontendRegistryService.listProviders().stream() + .map(provider -> toTemplate(provider.specification())) .sorted(Comparator.comparing(ProjectLanguageTemplate::languageId, String.CASE_INSENSITIVE_ORDER)) .toList(); } diff --git a/prometeu-studio/src/test/java/p/studio/projects/ProjectLanguageCatalogServiceTest.java b/prometeu-studio/src/test/java/p/studio/projects/ProjectLanguageCatalogServiceTest.java new file mode 100644 index 00000000..a02306af --- /dev/null +++ b/prometeu-studio/src/test/java/p/studio/projects/ProjectLanguageCatalogServiceTest.java @@ -0,0 +1,18 @@ +package p.studio.projects; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ProjectLanguageCatalogServiceTest { + + @Test + void shouldListLanguagesFromRegisteredProviders() { + final var service = new ProjectLanguageCatalogService(); + + final var templates = service.listLanguageTemplates(); + + assertEquals(1, templates.size()); + assertEquals("pbs", templates.getFirst().languageId()); + } +} -- 2.47.2 From 6fdb4828c3269aee826a9c7b697bba53cf597196 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:37:22 +0100 Subject: [PATCH 6/6] housekeep DSC-0054 --- discussion/index.ndjson | 4 +- ...nd-providers-before-plugin-architecture.md | 74 +++++++++++++++ ...D-0057-multi-frontend-provider-contract.md | 94 ------------------- ...der-explicito-como-contrato-de-frontend.md | 92 ------------------ ...frontend-provider-and-registry-contract.md | 71 -------------- ...introduce-frontendprovider-registry-api.md | 69 -------------- ...-wrap-pbs-frontend-as-explicit-provider.md | 73 -------------- ...ate-common-consumers-to-provider-lookup.md | 74 --------------- 8 files changed, 76 insertions(+), 475 deletions(-) create mode 100644 discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md delete mode 100644 discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md delete mode 100644 discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md delete mode 100644 discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md delete mode 100644 discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md delete mode 100644 discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md delete mode 100644 discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 3494e7d9..731aace8 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":55,"CLSN":1}} +{"type":"meta","next_id":{"DSC":66,"AGD":69,"DEC":41,"PLN":107,"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":[]} @@ -10,7 +10,7 @@ {"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-0054","status":"in_progress","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":[{"id":"AGD-0057","file":"AGD-0057-multi-frontend-provider-contract.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0040","file":"DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0057"}],"plans":[{"id":"PLN-0103","file":"PLN-0103-specify-frontend-provider-and-registry-contract.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0104","file":"PLN-0104-introduce-frontendprovider-registry-api.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0105","file":"PLN-0105-wrap-pbs-frontend-as-explicit-provider.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]},{"id":"PLN-0106","file":"PLN-0106-migrate-common-consumers-to-provider-lookup.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0040"]}],"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":[]} {"type":"discussion","id":"DSC-0051","status":"open","ticket":"pbs-lsp-diagnostics-ux","title":"PBS LSP Diagnostics UX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","diagnostics","ux"],"agendas":[{"id":"AGD-0054","file":"AGD-0054-pbs-lsp-diagnostics-ux.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md b/discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md new file mode 100644 index 00000000..9958d468 --- /dev/null +++ b/discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md @@ -0,0 +1,74 @@ +--- +id: LSN-0055 +ticket: multi-frontend-provider-contract +title: Static frontend providers before plugin architecture +created: 2026-07-15 +tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] +--- + +## Context + +Prometeu needed a multi-frontend boundary without turning the compiler or Studio into a dynamic plugin platform. Before this work, shared code could ask the registry for frontend specs or phase services, and PBS was registered directly as the default language. That worked for a single frontend, but it made the next frontend harder because common code could still depend on PBS-specific construction details. + +The durable ownership rule is now: common compiler and Studio code select a frontend by `languageId`, then consume a provider contract. PBS remains the first and only real provider, but it is no longer the shape of the shared abstraction. + +## Key Decisions + +### `FrontendProvider` is the common registration unit + +**What:** Each registered frontend is represented by a `FrontendProvider` with: + +- `specification()`, for the static frontend contract and `languageId`; +- `compiler()`, for compiler-facing frontend execution; +- `languageService()`, as an optional editor-facing capability. + +**Why:** This groups the frontend identity, compiler entrypoint, and optional tooling capability without forcing every frontend to implement Studio/editor services. + +**Trade-offs:** The provider is intentionally small. It does not solve dynamic discovery, plugin installation, external loading, or all future language-service APIs. Those are separate architectural decisions. + +### Registration is explicit + +**What:** Frontend registration is static and composition-root-owned. The application composition path bootstraps the default provider set, and the registry resolves providers by `languageId`. + +**Why:** Explicit registration keeps dependencies visible and testable. It lets composition know about PBS while preventing common compiler and Studio consumers from directly constructing PBS services. + +**Trade-offs:** Adding a new in-repository frontend still requires a code change in composition. That is acceptable because this decision optimizes for repository-internal multi-frontend readiness, not external plugin extensibility. + +### PBS is a provider, not the shared model + +**What:** PBS is wrapped by `PBSFrontendProvider`. Shared build and Studio consumers obtain frontend behavior through `FrontendRegistryService.require(languageId)` or provider-derived listings. + +**Why:** PBS remains the correctness baseline, but it must not become the exclusive owner of compiler pipeline semantics. + +**Trade-offs:** PBS-specific tests may still instantiate `PBSFrontendPhaseService` directly because they test PBS internals. Common modules should not. + +## Patterns and Algorithms + +Use this path for common compiler execution: + +1. Resolve the project language from the manifest or default provider. +2. Resolve `FrontendProvider` by `languageId`. +3. Use `provider.specification()` for static metadata. +4. Use `provider.compiler()` for frontend compilation. +5. Use `provider.languageService()` only when a tooling consumer needs optional editor services. + +Use this path for Studio language catalogs: + +1. List providers from the registry. +2. Derive templates from `provider.specification()`. +3. Do not hardcode PBS templates in Studio catalog code. + +## Pitfalls + +- Do not add reflection, classpath scanning, external JAR loading, or runtime plugin installation to solve repository-internal frontend registration. +- Do not make `languageService()` mandatory. Compilation and editor assistance are separate capabilities. +- Do not instantiate `PBSFrontendPhaseService` from common build, dependency, Studio, or app code. +- Do not use PBS as a fallback for unknown `languageId`. Unknown languages must fail explicitly. +- Do not move frontend semantic ownership into Studio just because Studio consumes provider metadata. + +## Takeaways + +- Static providers are enough to prepare for multiple in-repository frontends. +- The registry boundary is provider-based, not PBS-based. +- Composition may know which frontends exist; common consumers should only know `FrontendProvider`. +- Optional editor capabilities keep compiler readiness independent from Studio feature depth. diff --git a/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md b/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md deleted file mode 100644 index dbb0267f..00000000 --- a/discussion/workflow/agendas/AGD-0057-multi-frontend-provider-contract.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -id: AGD-0057 -ticket: multi-frontend-provider-contract -title: Introduzir provider completo de frontend -status: accepted -created: 2026-07-15 -resolved: -decision: -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -# Agenda - Introduzir provider completo de frontend - -## Objetivo - -Domain owner: `compiler/general`, com impacto em `studio`. - -Discutir como consolidar um contrato de `FrontendProvider` que agrupe especificacao, compilador e servicos editoriais opcionais sem transformar o Studio em uma plataforma de plugins. - -## Contexto atual - -O repositorio ja possui `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` e superficies relacionadas a `FrontendSpec`, `FrontendPhaseService` e `languageId`. Ainda ha sinais de registro ou uso direto do PBS em composition roots e chamadas comuns. - -## Escopo - -- Inspecionar o registry atual e seus consumidores. -- Definir se `FrontendProvider` deve ser novo contrato ou evolucao de contrato existente. -- Planejar `PBSFrontendProvider` como unico provider inicial. -- Preservar selecao atual por `languageId`. - -## Fora de escopo - -- Descoberta dinamica de plugins. -- Reflection, classpath scanning ou carregamento externo de JARs. -- Implementar qualquer frontend real alem do PBS. - -## Arquivos e componentes a inspecionar - -- `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` -- `prometeu-compiler/frontends/prometeu-frontend-pbs/...` -- `prometeu-compiler/prometeu-build-pipeline/...` -- `prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java` -- `prometeu-app/src/main/java/p/studio/AppContainer.java` - -## Alteracoes propostas - -Opcao A: criar `FrontendProvider` explicito com `specification()`, `compiler()` e `languageService()` opcional. - -Opcao B: evoluir o registry para devolver um objeto existente que ja represente provider, adicionando apenas os campos faltantes. - -Recomendacao inicial: preferir a menor mudanca que faca o codigo comum resolver `provider = registry.require(languageId)` e pare de conhecer classes PBS fora do composition root. - -## Estrategia de implementacao - -Comecar por uma auditoria de chamadas atuais ao registry e de instanciacoes diretas do PBS. Introduzir o contrato sem remover APIs antigas no mesmo passo, migrar PBS para o contrato e so entao substituir consumidores comuns. - -## Testes necessarios - -- Teste do registry exigindo resolucao por `languageId`. -- Teste de registro unico do PBS como provider inicial. -- Teste de erro claro para `languageId` desconhecido. - -## Criterios de aceitacao - -- O codigo comum consulta o provider, nao instancia `PBSFrontendPhaseService`. -- PBS permanece funcional. -- Nenhum frontend real novo e criado. - -## Riscos - -- Criar uma abstracao grande demais antes de mapear os consumidores reais. -- Misturar contrato de build com contrato editorial. - -## Decisoes que devem ser registradas - -- Nome final do contrato. -- Responsabilidades minimas do provider. -- Onde fica o composition root autorizado a registrar PBS. - -## Resolucao aceita - -O contrato deve ser introduzido como `FrontendProvider`. - -Responsabilidades minimas: - -- expor a especificacao do frontend por `specification()`; -- expor o compilador ou fase de compilacao equivalente por `compiler()`; -- expor servicos editoriais por `languageService()` somente como capacidade opcional, quando necessaria para o Studio. - -O contrato nao deve incluir descoberta dinamica de plugins, reflection, classpath scanning ou carregamento externo de JARs. - -O registro inicial deve continuar explicito no composition root da aplicacao, com `prometeu-app/src/main/java/p/studio/AppContainer.java` como ponto preferencial de composicao. Codigo comum deve consumir o provider via `registry.require(languageId)` e nao deve instanciar diretamente classes PBS, incluindo `PBSFrontendPhaseService`. - -PBS permanece o unico provider inicial. Nenhum frontend real novo deve ser criado por esta frente. diff --git a/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md b/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md deleted file mode 100644 index b9782807..00000000 --- a/discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: DEC-0040 -ticket: multi-frontend-provider-contract -title: FrontendProvider explicito como contrato de frontend -status: accepted -created: 2026-07-15 -ref_agenda: AGD-0057 -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -## Context - -This decision belongs to domain owner `compiler/general`, with impact on `studio`. - -The repository already has `FrontendRegistryService`, `FrontendSpec`, `FrontendPhaseService`, and `languageId` based selection. Those surfaces are enough to keep PBS working, but common compiler and Studio code still has places where PBS-specific classes or assumptions can leak into composition and consumption paths. - -The multi-frontend direction requires a stable provider boundary before removing PBS-specific branches from common code. The boundary must make frontend registration explicit without turning the Studio or compiler into a dynamic plugin platform. - -This decision resolves `AGD-0057`. - -## Decision - -The repository MUST introduce an explicit `FrontendProvider` contract as the common frontend registration unit. - -`FrontendProvider` MUST expose the following minimum responsibilities: - -- `specification()`: returns the frontend specification, including its stable `languageId`; -- `compiler()`: returns the compiler-facing frontend service or phase equivalent used by the build pipeline; -- `languageService()`: returns an optional editor-facing language service capability for Studio consumers. - -`languageService()` MUST be optional. A frontend that can compile but does not provide editor services MUST remain a valid provider. - -`FrontendRegistryService` MUST resolve providers by `languageId`. The common consumption shape SHOULD become `provider = registry.require(languageId)` or an equivalent explicit lookup that fails clearly for unknown languages. - -PBS MUST be registered as the only initial real provider through a `PBSFrontendProvider` or equivalent concrete provider object. This work MUST NOT introduce another real frontend. - -Provider registration MUST remain explicit in the application composition root. `prometeu-app/src/main/java/p/studio/AppContainer.java` is the preferred initial composition point for registering the PBS provider. - -Common compiler, build pipeline, and Studio code MUST NOT instantiate PBS-specific frontend services directly. In particular, common code MUST NOT directly instantiate `PBSFrontendPhaseService`; it MUST obtain the relevant service through the provider resolved from the registry. - -This decision MUST NOT introduce dynamic plugin discovery, reflection-based discovery, classpath scanning, external JAR loading, or runtime plugin installation. - -## Rationale - -An explicit provider object gives the project one stable unit for frontend identity, compilation, and optional editorial capability. It keeps `languageId` as the selection key while avoiding scattered direct knowledge of PBS in common code. - -Keeping the provider small prevents a premature plugin architecture. The immediate goal is static multi-frontend readiness inside the repository, not external extensibility. - -Making language services optional separates build correctness from Studio editor assistance. A frontend should be able to participate in compilation without being forced to implement editor features in the same wave. - -Using the application composition root for registration keeps ownership clear: composition may know that PBS exists, but shared compiler and Studio consumers should only know the provider contract. - -## Implications - -- `FrontendRegistryService` will need to evolve from spec/phase lookups into provider lookup, while preserving compatibility during migration where necessary. -- Existing PBS registration must be wrapped behind a provider object. -- Common consumers that currently request `FrontendSpec` or `FrontendPhaseService` directly may be migrated incrementally to provider lookup. -- Studio catalog code may continue listing specifications, but its source should become provider-derived rather than PBS-specific. -- Build pipeline code should obtain compiler-facing frontend behavior from the resolved provider. -- Error handling for unknown `languageId` must remain explicit and diagnostic-friendly. -- No product or runtime behavior should change for PBS as the only registered provider. - -## Propagation Targets - -- specs: - - Add or update a `compiler/general` specification for the frontend provider and registry contract. - - Reference Studio-facing optional language service capability where relevant. -- plans: - - Create an implementation plan for provider contract introduction, PBS provider registration, consumer migration, and tests. -- code: - - `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` - - PBS frontend module provider implementation. - - `prometeu-compiler/prometeu-build-pipeline/...` consumers that resolve frontend services. - - `prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java` - - `prometeu-app/src/main/java/p/studio/AppContainer.java` -- tests: - - Registry resolves a provider by `languageId`. - - PBS is registered as the only initial real provider. - - Unknown `languageId` fails with a clear error. - - Common code can obtain compiler-facing frontend behavior without directly instantiating `PBSFrontendPhaseService`. -- docs: - - Decision-derived implementation plan. - - Lessons after implementation and housekeeping, if the completed work produces reusable guidance. - -## References - -- Agenda: AGD-0057 -- Source discussion: DSC-0054 - -## Revision Log - -- 2026-07-15: Initial decision drafted from accepted `AGD-0057`. diff --git a/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md b/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md deleted file mode 100644 index e16d4b3c..00000000 --- a/discussion/workflow/plans/PLN-0103-specify-frontend-provider-and-registry-contract.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: PLN-0103 -ticket: multi-frontend-provider-contract -title: Specify frontend provider and registry contract -status: done -created: 2026-07-15 -ref_decisions: [DEC-0040] -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -## Briefing - -DEC-0040 locks an explicit `FrontendProvider` contract as the common frontend registration unit. The first implementation step is to make that contract normative in the compiler/general specs before changing code. - -Domain owner: `compiler/general`, with impact on `studio`. - -## Objective - -Specify the frontend provider and registry contract so implementation can introduce the API without relying on implicit behavior or PBS-specific assumptions. - -## Dependencies - -- Accepted decision: `DEC-0040`. -- Existing compiler specs under `docs/specs/compiler/`. -- Existing Studio/editor references may be linked but must not become the owner of the contract. - -## Scope - -- Add or update a compiler/general spec section defining `FrontendProvider`. -- Define required provider responsibilities: - - `specification()`; - - `compiler()`; - - optional `languageService()`. -- Define `languageId` as the registry lookup key. -- Define explicit provider registration as the only supported v1 registration model. -- Define PBS as the only initial real provider. -- Define unknown-language failure behavior as explicit and diagnostic-friendly. -- Define that common code must obtain compiler-facing frontend behavior through provider lookup. - -## Non-Goals - -- Do not specify dynamic plugin discovery. -- Do not specify reflection, classpath scanning, external JAR loading, or runtime plugin installation. -- Do not introduce a second real frontend. -- Do not define the full Studio language-service API beyond optional provider capability. - -## Execution Method - -1. Inspect existing compiler/general spec organization and choose the nearest owner document for registry and frontend composition. -2. Add a `FrontendProvider` section with normative `MUST` language for required and optional responsibilities. -3. Add a registry section stating that providers are resolved by `languageId` and that unknown languages fail clearly. -4. Add a registration section stating that provider registration is explicit and composition-root-owned. -5. Add a PBS v1 section stating that PBS is the only initial real provider and no new frontend is introduced by this work. -6. Cross-reference Studio only as an optional language-service consumer, not as the owner of the provider contract. - -## Acceptance Criteria - -- A compiler/general spec defines `FrontendProvider`, registry lookup, explicit registration, and PBS-only initial provider status. -- The spec prohibits plugin discovery, reflection discovery, scanning, external JAR loading, and runtime plugin installation for this decision. -- The spec makes `languageService()` optional and does not require editor support for a compilable frontend. -- The spec is written in English. - -## Tests - -- Documentation validation through review against `DEC-0040`. -- No code tests are required in this plan. - -## Affected Artifacts - -- `docs/specs/compiler/...` -- `discussion/workflow/decisions/DEC-0040-frontendprovider-explicito-como-contrato-de-frontend.md` diff --git a/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md b/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md deleted file mode 100644 index c0a65a12..00000000 --- a/discussion/workflow/plans/PLN-0104-introduce-frontendprovider-registry-api.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: PLN-0104 -ticket: multi-frontend-provider-contract -title: Introduce FrontendProvider registry API -status: done -created: 2026-07-15 -ref_decisions: [DEC-0040] -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -## Briefing - -DEC-0040 requires common code to resolve frontend behavior through a provider. This plan introduces the API surface in the frontend registry without forcing all consumers to migrate in the same change. - -Domain owner: `compiler/general`. - -## Objective - -Introduce `FrontendProvider` and provider-based registry lookup while preserving existing PBS behavior during migration. - -## Dependencies - -- `PLN-0103` should define the normative spec first. -- Accepted decision: `DEC-0040`. -- Existing registry module: `prometeu-compiler/prometeu-frontend-registry`. - -## Scope - -- Add the `FrontendProvider` contract in the frontend registry module. -- Add an optional language-service return shape, using an existing interface if one already exists or a minimal neutral placeholder only if required. -- Add provider registration and provider lookup by `languageId`. -- Add `require(languageId)` or equivalent explicit lookup that fails clearly for unknown languages. -- Preserve compatibility methods during migration if existing consumers still call spec or phase lookup. - -## Non-Goals - -- Do not register PBS in this plan unless needed for API tests with a simple fixture. -- Do not migrate build pipeline or Studio consumers in this plan. -- Do not add plugin discovery, reflection, scanning, external JAR loading, or runtime plugin installation. -- Do not define a broad editor API. - -## Execution Method - -1. Inspect `FrontendRegistryService`, `FrontendSpec`, and `FrontendPhaseService` to confirm current method names and package ownership. -2. Add `FrontendProvider` to the registry-facing package with `specification()`, `compiler()`, and optional `languageService()`. -3. Update `FrontendRegistryService` so its primary storage is provider keyed by `languageId`. -4. Add `require(languageId)` or the nearest local naming equivalent for provider lookup. -5. Keep old spec/phase accessor methods as provider-derived compatibility wrappers if they are still used. -6. Add registry unit tests for provider registration, provider lookup, duplicate language handling if currently supported, and unknown-language errors. - -## Acceptance Criteria - -- `FrontendProvider` exists and exposes all responsibilities required by `DEC-0040`. -- `FrontendRegistryService` can resolve a provider by `languageId`. -- Unknown `languageId` lookup fails with a clear exception or diagnostic message. -- Existing callers can still compile until their migration plan runs. - -## Tests - -- Registry test: registered provider is returned by `languageId`. -- Registry test: unknown `languageId` fails clearly. -- Registry test: provider-derived spec listing remains correct if compatibility methods remain. -- Run the relevant Gradle test task for `prometeu-frontend-registry`. - -## Affected Artifacts - -- `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` -- New `FrontendProvider` contract in the same registry API surface. -- Registry tests under `prometeu-compiler/prometeu-frontend-registry/src/test/...` diff --git a/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md b/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md deleted file mode 100644 index 2d2b024b..00000000 --- a/discussion/workflow/plans/PLN-0105-wrap-pbs-frontend-as-explicit-provider.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: PLN-0105 -ticket: multi-frontend-provider-contract -title: Wrap PBS frontend as explicit provider -status: done -created: 2026-07-15 -ref_decisions: [DEC-0040] -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -## Briefing - -DEC-0040 requires PBS to become the only initial real provider behind the new `FrontendProvider` contract. This plan wraps existing PBS frontend behavior without changing PBS product behavior. - -Domain owner: `compiler/general`, with implementation in `compiler/pbs` and composition impact in `prometeu-app`. - -## Objective - -Create and register an explicit PBS provider through the application composition root. - -## Dependencies - -- `PLN-0104` must introduce `FrontendProvider` and provider lookup first. -- Accepted decision: `DEC-0040`. -- Existing PBS frontend phase/service implementation. -- Application composition root in `prometeu-app`. - -## Scope - -- Add `PBSFrontendProvider` or equivalent concrete provider object. -- Make the provider return the existing PBS `FrontendSpec`. -- Make the provider return the existing PBS compiler-facing service or phase. -- Return no language service, or the existing PBS language-service adapter only if already present and compatible. -- Register PBS explicitly in `prometeu-app/src/main/java/p/studio/AppContainer.java` or the nearest current application composition point. -- Ensure PBS remains the only initial real provider. - -## Non-Goals - -- Do not create another real frontend. -- Do not change PBS parsing, semantics, lowering, or runtime output. -- Do not migrate all common consumers in this plan. -- Do not introduce dynamic provider discovery. - -## Execution Method - -1. Inspect PBS frontend module boundaries and locate the current `FrontendSpec` and `FrontendPhaseService` construction. -2. Add `PBSFrontendProvider` in the PBS frontend module or an existing integration package that can legally depend on PBS. -3. Implement `specification()` and `compiler()` by delegating to the existing PBS objects. -4. Implement `languageService()` as empty unless a current Studio-compatible PBS language service already exists. -5. Update `AppContainer` or the existing composition root to register the PBS provider explicitly with `FrontendRegistryService`. -6. Remove direct PBS registration paths that duplicate the provider registration if they become redundant. -7. Add tests proving only PBS is registered as the real provider in the default composition path. - -## Acceptance Criteria - -- PBS is represented by a concrete provider object. -- Default application composition registers PBS explicitly as a provider. -- PBS remains functional through existing compile/build flows. -- No additional real frontend is introduced. -- No dynamic discovery mechanism is added. - -## Tests - -- Provider test: `PBSFrontendProvider.specification()` returns the PBS language id. -- Provider test: `PBSFrontendProvider.compiler()` returns working compiler-facing behavior. -- Composition test: default registry contains PBS as the only real provider. -- Existing PBS compile/build tests continue to pass. - -## Affected Artifacts - -- PBS frontend module under `prometeu-compiler/frontends/prometeu-frontend-pbs/...` -- `prometeu-app/src/main/java/p/studio/AppContainer.java` -- Registry or application composition tests. diff --git a/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md b/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md deleted file mode 100644 index a1400a7a..00000000 --- a/discussion/workflow/plans/PLN-0106-migrate-common-consumers-to-provider-lookup.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: PLN-0106 -ticket: multi-frontend-provider-contract -title: Migrate common consumers to provider lookup -status: done -created: 2026-07-15 -ref_decisions: [DEC-0040] -tags: [compiler, compiler-general, studio, frontend, registry, multi-frontend] ---- - -## Briefing - -DEC-0040 forbids common compiler, build pipeline, and Studio code from directly instantiating PBS-specific frontend services. After the registry API and PBS provider exist, consumers must move to provider lookup. - -Domain owner: `compiler/general`, with impact on `studio`. - -## Objective - -Migrate common consumers from direct spec/phase/PBS access to provider-based lookup by `languageId`. - -## Dependencies - -- `PLN-0104` must provide provider lookup. -- `PLN-0105` must register PBS as a provider. -- Accepted decision: `DEC-0040`. - -## Scope - -- Audit common compiler, build pipeline, Studio, and app code for direct PBS frontend service construction. -- Replace common code service lookup with provider lookup. -- Make build pipeline frontend execution obtain compiler-facing behavior from `provider.compiler()`. -- Make Studio project language catalog list specifications from providers. -- Keep PBS-specific construction inside PBS provider or composition root only. -- Add or update tests that prove common code does not directly instantiate `PBSFrontendPhaseService`. - -## Non-Goals - -- Do not remove compatibility registry APIs unless all callers have migrated and the removal is local. -- Do not introduce new frontend behavior. -- Do not change backend IR, validation boundaries, or lifecycle semantics beyond provider lookup. -- Do not implement optional Studio language services that do not already exist. - -## Execution Method - -1. Search for `PBSFrontendPhaseService`, PBS frontend constructors, `getFrontendPhaseService`, and `getFrontendSpec` usage outside PBS and composition-owned code. -2. Classify each usage as composition-owned, PBS-owned, or common consumer. -3. Update common consumers to resolve `FrontendProvider` by `languageId`. -4. Update `FrontendPhasePipelineStage` so it calls provider compiler behavior rather than direct phase lookup. -5. Update `ProjectLanguageCatalogService` so its catalog is provider-derived. -6. Keep compatibility wrappers only where they reduce migration risk and are provider-derived. -7. Add architectural tests or focused unit tests that fail if common modules instantiate `PBSFrontendPhaseService` directly. -8. Run relevant compiler, build pipeline, Studio, and app tests. - -## Acceptance Criteria - -- Common compiler/build pipeline/Studio code obtains frontend behavior through provider lookup. -- Direct `PBSFrontendPhaseService` instantiation remains only in PBS provider or approved composition code. -- `ProjectLanguageCatalogService` is provider-derived. -- Unknown `languageId` failures remain clear after consumer migration. -- PBS compile/build behavior remains unchanged. - -## Tests - -- Unit or integration test: build pipeline resolves PBS through provider and compiles an existing PBS fixture. -- Unit test: Studio language catalog lists PBS from provider specs. -- Architecture test or grep-backed test: common modules do not instantiate `PBSFrontendPhaseService`. -- Existing PBS and build pipeline tests pass. - -## Affected Artifacts - -- `prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java` -- `prometeu-studio/src/main/java/p/studio/projects/ProjectLanguageCatalogService.java` -- Common code currently using `FrontendRegistryService.getFrontendSpec` or `getFrontendPhaseService`. -- Tests in compiler, build pipeline, Studio, and app modules. -- 2.47.2