prometeu-studio/discussion/lessons/DSC-0065-multi-frontend-avoid-premature-abstractions/LSN-0067-multi-frontend-phase-rejects-premature-infrastructure.md
bQUARKz 4574aa17c3
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
implements PLN-0130
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.
2026-09-19 03:44:10 +01:00

6.4 KiB

id ticket title created tags
LSN-0067 multi-frontend-avoid-premature-abstractions Multi-frontend phase rejects premature infrastructure 2026-09-19
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