prometeu-studio/discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md
bQUARKz 6fdb4828c3
All checks were successful
JaCoCo Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 61.49% (17397/28294) * Branch Coverage: 52.32% (6724/12852) * Lines of Code: 28294 * Cyclomatic Complexity: 11339 #### Quality Gates Summary Output truncated.
Test / Build skipped: 15, passed: 608
Intrepid/Prometeu/Studio/pipeline/pr-master This commit looks good
housekeep DSC-0054
2026-07-15 08:37:22 +01:00

75 lines
4.2 KiB
Markdown

---
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.