Some checks are pending
Intrepid/Prometeu/Studio/pipeline/pr-master Build started...
JaCoCo Coverage #### Project Overview
No changes detected, that affect the code coverage.
* Line Coverage: 62.10% (17811/28682)
* Branch Coverage: 52.81% (6878/13025)
* Lines of Code: 28682
* Cyclomatic Complexity: 11494
#### Quality Gates Summary
Output truncated.
Test / Build skipped: 15, passed: 654
Record the multi-frontend simplicity guardrails in an English lesson: static registry is allowed, new abstractions need a real in-repo consumer, and plugin-style infrastructure stays forbidden. Housekeep DSC-0065 with LSN-0067.
168 lines
6.4 KiB
Markdown
168 lines
6.4 KiB
Markdown
---
|
|
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`
|