prometeu-studio/discussion/lessons/DSC-0057-multi-frontend-frontend-backend-contract/LSN-0059-common-irbackend-handoff-and-backend-guardrails.md
bQUARKz b9a32e460a
All checks were successful
JaCoCo Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 61.73% (17588/28493) * Branch Coverage: 52.44% (6777/12924) * Lines of Code: 28493 * Cyclomatic Complexity: 11423 #### Quality Gates Summary Output truncated.
Test / Build skipped: 15, passed: 619
Intrepid/Prometeu/Studio/pipeline/pr-master This commit looks good
Intrepid/Prometeu/Studio/pipeline/head This commit looks good
housekeep DSC-0057
2026-07-15 12:18:44 +01:00

5.7 KiB

id ticket title created tags
LSN-0059 multi-frontend-frontend-backend-contract Common IRBackend handoff and backend guardrails 2026-07-15
compiler
compiler-general
compiler-pbs
ir
backend
multi-frontend

Common IRBackend handoff and backend guardrails

Context

The multi-frontend work needed a clear boundary between language-specific frontends and common backend stages.

The existing code was already close to the desired architecture: PBS parsing, AST construction, and semantic analysis lowered into IRBackend, while the backend consumed IRBackend and lowered it into IRVM. The risk was not a known broken dependency. The risk was that common backend behavior still looked PBS-owned in specs, names, and missing guardrails, which could invite future coupling when another frontend is introduced.

Key Decisions

IRBackend is the common executable handoff

What: IRBackend remains the normative frontend-to-backend executable handoff. Frontends emit it; common backend stages consume it.

Why: The existing model already provides a language-neutral executable contract with modules, callable identities, executable functions, instruction metadata, globals, synthetic functions, host calls, intrinsics, spans, and capabilities. Renaming or redesigning it without a concrete leak would add churn without improving the boundary.

Trade-offs: Keeping the name IRBackend means the architecture relies on documentation and tests to communicate its common role. That is acceptable because the name is already established and the guardrails now enforce the boundary.

PBS owns lowering into IRBackend, not backend consumption of it

What: PBS specs describe PBS admission and translation into IRBackend. Compiler-general specs describe the common IRBackend -> IRVM contract and backend obligations.

Why: PBS is currently the only rich frontend producing executable IRBackend, so many examples naturally come from PBS. Specs must still separate source-language obligations from backend obligations so future frontends do not inherit PBS-specific rules by accident.

Trade-offs: Some PBS-facing examples remain useful, especially around lifecycle wrappers and asset metadata. They must be phrased as current frontend sources of a common backend obligation, not as backend ownership by PBS.

Implementation Result

The completed work:

  1. rewrote the general backend spec so IRBackend -> IRVM is explicitly compiler-general;
  2. rewrote the PBS lowering spec so PBS emits the common handoff instead of owning backend behavior;
  3. updated the conformance matrix with DEC-0043 guardrail rows;
  4. added a direct backend test that manually constructs common IRBackend and lowers it without PBS parser or frontend services;
  5. added an architectural test preventing common backend imports from p.studio.compiler.pbs;
  6. added a reflection-based contract test preventing public IRBackend model types from exposing PBS packages;
  7. renamed the common lifecycle helper from validatePbsLifecycleStructure to validateCommonLifecycleStructure.

Patterns and Algorithms

Boundary consolidation before abstraction

When an existing boundary is already technically sound, prefer consolidation over redesign:

  1. document the current contract as normative;
  2. identify only concrete leaks;
  3. add tests that would fail if the boundary regresses;
  4. avoid renames or model extraction until there is evidence of real coupling.

This keeps multi-frontend preparation focused on preventing regressions rather than inventing abstractions prematurely.

Guardrails for common backend neutrality

A useful backend neutrality guardrail has two layers:

  1. source/package guard: common backend source must not import language frontend packages;
  2. public-contract guard: common handoff types must not expose language-owned types through fields, constructors, methods, or record components.

The package guard catches implementation coupling. The reflection guard catches API coupling.

Direct handoff construction test

A backend test should be able to construct executable IRBackend manually using only common model types and lower it through LowerToIRVMService.

That test proves the backend consumes the contract, not a specific frontend pipeline.

Pitfalls

  • Do not treat the presence of PBS examples as proof that the backend is PBS-owned.
  • Do not move PBS source rules into compiler-general specs.
  • Do not let lifecycle terms such as published wrapper, boot guard, or frame root hide whether the obligation is common or PBS-specific.
  • Do not rename IRBackend for aesthetics when the real problem is missing ownership language and missing guardrails.
  • Do not use a future synthetic test frontend as a substitute for simple direct IRBackend construction tests.

Takeaways

  • IRBackend is the common executable handoff.
  • PBS owns PBS-to-IRBackend lowering; compiler-general owns IRBackend -> IRVM.
  • Common backend code must not depend on p.studio.compiler.pbs.
  • Public IRBackend contract types must not expose PBS AST, token, parser, semantic, or editorial types.
  • Multi-frontend preparation should first lock existing good boundaries before introducing new abstractions.

References

  • docs/specs/compiler/20. IRBackend to IRVM Lowering Specification.md
  • docs/specs/compiler/22. Backend Spec-to-Test Conformance Matrix.md
  • docs/specs/compiler-languages/pbs/13. Lowering IRBackend Specification.md
  • prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/backend/irvm/LowerToIRVMServiceTest.java
  • prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/CommonBackendArchitectureTest.java
  • prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/models/IRBackendExecutableContractTest.java