--- id: LSN-0067 ticket: multi-frontend-avoid-premature-abstractions title: Multi-frontend phase rejects premature infrastructure created: 2026-09-19 tags: [compiler, compiler-general, studio, frontend, architecture, multi-frontend, simplicity] --- # Multi-frontend phase rejects premature infrastructure ## Original Problem The multi-frontend preparation needed a standing simplicity rule. The original agenda asked for that rule *before* the other multi-frontend discussions. Those discussions already closed (DSC-0054 through DSC-0064). The remaining risk was not a missing plugin platform. The remaining risk was twofold: 1. using "keep it simple" to put PBS construction back into common compiler, Studio, LSP, or app code; 2. inventing marketplace, JAR loading, RPC, validator-core, or a generic SPI "for a future language" that does not exist in this repository. `FrontendRegistryService` is a static singleton. The original agenda listed a global service locator as out of scope. Without an explicit exception, a later change could inject a `Registry` into the pipeline for purity, which DSC-0063 already refused. ## Consolidated Decision This is standing policy for *future* work in the current phase: PBS as the only product frontend, `synth` as a test-only provider, frontends in-repo. It is not an audit of closed discussions and must not rewrite them. Durable locks from DEC-0051: - Implementation of this discussion is the decision plus this lesson. There is no new spec, no new ArchUnit rule, and no production refactor. - Spec 23 §2 and §8.3 remain the discovery MUST NOT surface. Do not copy those sentences into a new spec. - Architectural tests stay owned by LSN-0066. ### Static registry is allowed `FrontendRegistryService` as a static singleton, with public `register` and `unregister` and `bootstrapDefaults()` registering only PBS, is the composition mechanism of this phase. Treat that as an explicit exception, not as a banned service locator. Discovery must not use `ServiceLoader`, classpath scanning, reflection-based discovery, an external JAR, or runtime plugin installation. Do not inject a `Registry` into the pipeline, LSP, or `AppContainer`. `AppContainer` is not a PBS composition root. It may call `FrontendRegistryService.bootstrapDefaults()`. It must not instantiate PBS types. ### Real in-repo consumer A new interface, module, SPI, generator, or framework is allowed only when a real in-repo consumer exists. In this phase that consumer is one of: - the PBS product frontend; - the `synth` test frontend; - a second product frontend accepted by its own decision. "For a future language", "for the marketplace", or "when we have plugins" is not a consumer. `FrontendProvider`, `IRBackend`, common lifecycle assembly, and test-only ArchUnit are not premature. They already have consumers. ### Forbidden in this phase Until a later decision authorizes it with a real consumer, do not introduce: 1. dynamic frontend discovery (plugin, `ServiceLoader`, scan, external JAR, runtime install); 2. RPC, sockets, a process supervisor, or version negotiation between compiler and frontend; 3. a marketplace, hot reload, or frontend sandbox; 4. a validator-core or generic validation framework; 5. an SDK schema/generator or `HOSTCALLS.csv` as canonical ABI (LSN-0064); 6. a product module `frontends/synth`; 7. an injected `Registry`, or `AppContainer` as the PBS composition root. This list is not a monorepo-wide simplicity charter. It does not govern JavaFX, packer, or LSP protocol design. Owner is `compiler/general`, with impact on `studio` on the multi-frontend axis. ### Neighbors stay closed Do not reinterpret, relax, "simplify", or reimplement: - provider/registry (LSN-0055 / spec 23 §8.3); - common lifecycle; - console ABI / PBS delivery; - `synth`; - ArchUnit / PBS module identity. Using this policy to keep `new PBSFrontendPhaseService()` (or equivalent) in common code is refused. That is PBS recoupling, not simplicity. A second product frontend needs its own decision. This lesson neither replaces that decision nor blocks it. ## Final Implementation No production Java, Gradle, spec, or ArchUnit file changed. The map above is the implementation. Future compiler/studio plans on this axis should cite it when they propose a new module, SPI, or discovery mechanism. Code that already matches the phase: - `FrontendProvider` exposes `specification()`, `compiler()`, and optional `languageService()`; - `FrontendRegistryService.bootstrapDefaults()` registers PBS only; - `AppContainer` only calls that bootstrap; - `synth` lives in build-pipeline test sources; - ArchUnit lives in `:prometeu-architecture-tests`. ## Examples Good: - add a method to `FrontendProvider` because PBS or `synth` cannot compile or register without it; - keep `unregister` on the static registry so `synth` tests can clean up; - reject a proposal to load language JARs from a plugin directory. Bad: - inject `Registry` into `BuilderPipelineService` because static state looks like a service locator; - create `frontends/synth` as a product module; - add validator-core "so the next language has somewhere to put checks"; - keep `new PBSFrontendPhaseService()` in pipeline code and call that simpler than going through the provider. ## Pitfalls - The original agenda order ("before the other agendas") is historical. Do not reopen DSC-0054..DSC-0064 to satisfy it. - Static registry plus explicit `register`/`unregister` is visible. Hidden `ServiceLoader` discovery is not the same thing. - A second product frontend *is* a real consumer. Do not use this lesson to refuse that frontend; use it to refuse infrastructure that frontend does not yet need. - Spec 23 already forbids plugin discovery. Do not duplicate it. Do not treat silence in spec 23 as permission for RPC or validator-core. - Simplicity does not mean PBS may leak into common modules. LSN-0066 still owns that boundary. ## References - Decision: `DEC-0051` - Plan: `PLN-0130` - Related lessons: `LSN-0055`, `LSN-0060`, `LSN-0063`, `LSN-0064`, `LSN-0065`, `LSN-0066` - `docs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md` (§2, §8.3) - `prometeu-compiler/prometeu-frontend-registry/src/main/java/p/studio/compiler/FrontendRegistryService.java` - `prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.java` - `prometeu-app/src/main/java/p/studio/AppContainer.java`