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

99 lines
5.7 KiB
Markdown

---
id: LSN-0059
ticket: multi-frontend-frontend-backend-contract
title: Common IRBackend handoff and backend guardrails
created: 2026-07-15
tags: [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`