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.
6.4 KiB
| id | ticket | title | created | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| LSN-0067 | multi-frontend-avoid-premature-abstractions | Multi-frontend phase rejects premature infrastructure | 2026-09-19 |
|
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:
- using "keep it simple" to put PBS construction back into common compiler, Studio, LSP, or app code;
- 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
synthtest 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:
- dynamic frontend discovery (plugin,
ServiceLoader, scan, external JAR, runtime install); - RPC, sockets, a process supervisor, or version negotiation between compiler and frontend;
- a marketplace, hot reload, or frontend sandbox;
- a validator-core or generic validation framework;
- an SDK schema/generator or
HOSTCALLS.csvas canonical ABI (LSN-0064); - a product module
frontends/synth; - an injected
Registry, orAppContaineras 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:
FrontendProviderexposesspecification(),compiler(), and optionallanguageService();FrontendRegistryService.bootstrapDefaults()registers PBS only;AppContaineronly calls that bootstrap;synthlives in build-pipeline test sources;- ArchUnit lives in
:prometeu-architecture-tests.
Examples
Good:
- add a method to
FrontendProviderbecause PBS orsynthcannot compile or register without it; - keep
unregisteron the static registry sosynthtests can clean up; - reject a proposal to load language JARs from a plugin directory.
Bad:
- inject
RegistryintoBuilderPipelineServicebecause static state looks like a service locator; - create
frontends/synthas 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/unregisteris visible. HiddenServiceLoaderdiscovery 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.javaprometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendProvider.javaprometeu-app/src/main/java/p/studio/AppContainer.java