18 KiB
PBS Manifest, Module, Stdlib, and SDK Resolution Specification
Status: Draft v2 (Normative)
Applies to: prometeu.json, project and module terminology, workspace dependency resolution, stdlib selection, reserved stdlib projects, interface-module loading, and compile-time SDK metadata
1. Purpose
This document defines the normative compile-time model for:
- project manifests,
- project and module identity,
- import resolution,
- stdlib selection,
- reserved stdlib project spaces,
- stdlib interface modules,
- and the compile-time lifecycle of SDK host-binding metadata.
This document is the authority for how the compiler discovers and loads:
- ordinary project modules,
- reserved stdlib modules such as
@sdk:gfxand@sdk:composer, - compile-time reserved metadata attached to those reserved modules,
- interface-only service facades that wrap host surfaces for source ergonomics,
- and backend-provided compile surfaces consumed by the frontend for symbolic authoring.
This document does not define runtime load behavior. PBX host-binding emission and loader-side syscall resolution are defined by the Host ABI Binding and Loader Resolution Specification.
It also does not define the raw packer snapshot format. Frontend-facing compile surfaces consume only the backend-owned surface contract selected for the active build.
2. Scope
This document defines:
- the role of
languageinprometeu.json, - the role of
stdlibinprometeu.json, - the distinction between projects, modules, and imports,
- the distinction between ordinary project dependencies and the stdlib environment,
- root-project ownership of the effective stdlib line of a build,
- reserved project spaces such as
@sdk:*and@core:*, - the source model for stdlib interface modules,
- the compile-time role of reserved attributes such as
[Host(...)]. - the boundary between backend-owned compile surfaces and frontend semantic consumption.
This document does not define:
- PBX binary layout,
- loader-side syscall resolution,
- cartridge capability policy,
- package registry protocol details,
- runtime reflection over attributes,
- or the full operational snapshot model owned by packer.
3. Core Terms
3.5 Backend-owned frontend surface context
The compiler backend may provide a frontend-facing semantic surface context to the active language frontend.
Rules:
- The frontend surface context is backend-owned.
- The frontend surface context is not the raw operational snapshot owned by packer or other domain services.
- The frontend surface context exists to support semantic consumption, diagnostics, and tooling-oriented source interpretation.
- For PBS asset references in v1, the frontend surface context asset slice SHALL be
List<Addressable(address, asset_id)>. - Future surface slices MAY exist, but they are outside this document's v1 PBS asset contract.
3.1 Project
A project is the unit described by prometeu.json.
Rules:
- A project has a
name,version,language,stdlib, anddependencies. - A project is the unit resolved by the workspace dependency graph.
- A project is the unit selected by a dependency declaration.
- A project is the unit published and versioned by ordinary dependency resolution.
- A project contains one or more modules.
3.2 Module
A module is the unit of source import inside a project.
Rules:
- Every
.pbssource file belongs to exactly one module. - Every module belongs to exactly one project.
- Imports select modules, not whole projects.
- A module is addressed by a project name plus a module path.
3.3 Canonical module address
The canonical PBS module address format is:
@project:path/to/module
Rules:
projectidentifies the owning project space.path/to/moduleidentifies the module path inside that project.- Module path segments are directory-style segments separated by
/. - The syntax is Java-like in organization and JavaScript-like in import surface.
Examples:
@game:player/state@physics:collision/shapes@sdk:gfx@core:math/vector
3.4 Reserved project spaces
The following project spaces are reserved:
@sdk:*@core:*
Rules:
- Reserved project spaces belong to the selected stdlib environment.
- Ordinary user-authored projects MUST NOT publish modules into reserved project spaces.
- Ordinary dependency resolution MUST NOT satisfy
@sdk:*or@core:*imports from user projects. - Reserved project spaces are resolved only from the selected stdlib environment.
4. prometeu.json
4.1 Required fields
The manifest format relevant to this document is:
{
"name": "main",
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"dependencies": [
{ "name": "dep1", "version": "1.0.0" }
]
}
Rules:
nameidentifies the project.versionidentifies the project version.languageidentifies the frontend language.stdlibidentifies the selected stdlib major line.dependenciesdeclare ordinary project dependencies only.
4.2 language
Rules:
languageselects the compiler frontend.- All projects in one resolved workspace MUST use the same
language. - Unknown
languagevalues are compile-time errors.
4.3 stdlib
Rules:
stdlibis required in every manifest.stdlibuses major-only version syntax in v1.- The manifest surface for
stdlibis a string containing a positive decimal integer. - Examples of valid values:
"1","2". - Examples of invalid values:
"0","01","1.0","v1","". - Implementations SHOULD normalize
stdlibinternally to an integer major version.
Diagnostics:
- Missing
stdlibis a manifest error. - Invalid major-only format is a manifest error.
5. Ordinary Dependencies vs Stdlib Environment
5.1 Ordinary dependencies
Rules:
dependenciesmodel ordinary project relationships only.- A dependency may be local or registry-based according to the compiler's dependency resolver.
- Dependencies contribute source projects, modules, and project-graph edges.
dependenciesdo not declare stdlib projects.
5.2 Stdlib environment
Rules:
- The stdlib environment is not declared through
dependencies. - The stdlib environment is selected through
stdlib. @sdk:*and@core:*imports resolve against the stdlib environment selected for the build.- The presence of stdlib modules does not imply automatic visibility in source.
- User code MUST still import stdlib modules explicitly through ordinary import syntax.
Example:
import { Gfx, color } from @sdk:gfx;
let c: color = color.red;
Gfx.draw_pixel(1, 1, c);
Rules:
Gfxis not implicitly in scope.Gfxbecomes visible only throughimport.- The compiler accepts that import because the selected stdlib environment exposes
@sdk:gfx.
For sprite composition in stdlib line 1, the canonical reserved SDK surface is:
import { Composer } from @sdk:composer;
let status: int = Composer.emit_sprite(7, 0, 12, 18, 0, 2, false, false, 1);
Rules:
@sdk:composeris the canonical sprite-composition module in this wave.@sdk:gfxremains valid for primitive and overlay-oriented graphics operations.Gfx.set_spriteis not part of the active stdlib line1contract.
6. Effective Stdlib of the Build
The root project owns the effective stdlib line of the build.
Rules:
- The resolved workspace has exactly one effective stdlib major version.
- The effective stdlib major version is taken from the root project manifest.
- All projects in the workspace compile under that same effective stdlib line.
- Dependency projects do not activate separate stdlib environments for themselves.
This means:
stdlibon a dependency is a compatibility declaration,- not an instruction to switch the compiler into another stdlib mode for that dependency.
7. Stdlib Compatibility Across Dependency Projects
Let:
Rbe the root project'sstdlibmajor,Dbe a dependency project'sstdlibmajor.
Rules:
- If
D > R, dependency resolution MUST fail with a deterministic compile-time error. - If
D <= R, dependency resolution MAY proceed. D <= Rdoes not guarantee semantic compatibility of all APIs used by the dependency; it only means the dependency is not asking for a newer stdlib line than the root selected.
Rationale:
- the build target is chosen by the root project,
- dependency projects may target the same or an older stdlib line,
- dependency projects must not force the build to silently adopt a newer stdlib than the root requested.
Example:
- root
stdlib = "1", dependencystdlib = "2": error. - root
stdlib = "2", dependencystdlib = "1": allowed. - root
stdlib = "1", dependencystdlib = "1": allowed.
8. Import Resolution
8.1 Resolution sources
The compiler resolves imports against exactly two sources:
- the selected stdlib environment,
- the resolved ordinary project dependency graph.
Rules:
@sdk:*and@core:*are resolved only against the stdlib environment,- all other
@project:*imports are resolved only against the ordinary dependency graph, - there is no fallback from reserved stdlib resolution to ordinary dependencies,
- there is no fallback from ordinary dependency resolution to reserved stdlib spaces.
8.2 Resolution algorithm
For an import:
import { X } from @project:path/to/module;
9. Backend-Owned Symbolic Compile Surfaces
Some source-level semantics depend on backend-owned symbolic surfaces rather than on imported stdlib modules alone.
Rules:
- A symbolic compile surface consumed by the frontend MUST enter through the backend/frontend compile contract, not through direct frontend service queries.
- PBS symbolic asset references are resolved from the backend-owned frontend surface context rather than from stdlib import discovery.
- Stdlib interfaces such as
@sdk:assetdefine host-backed callable surfaces, but they do not replace backend ownership of symbolicAddressableresolution. - The backend/frontend contract MAY carry symbolic surfaces that are not themselves importable modules.
the compiler MUST:
- parse the project space and module path,
- determine whether the project space is reserved,
- if reserved, resolve the module from the selected stdlib environment,
- otherwise, resolve the module from the root project or its dependency graph,
- load the target module,
- resolve the requested exported names from that module.
Failure at any step is a deterministic compile-time error.
9. Stdlib Interface Modules
9.1 Interface-module model
The selected stdlib environment MUST provide its modules as PBS-like interface modules.
Rules:
- Stdlib modules are
.pbsmodules loaded by the compiler. - Stdlib interface modules use the same parser surface as ordinary PBS modules.
- Stdlib interface modules are interpreted in interface-module mode.
- Interface-module mode is non-executable and compile-time only.
- Interface modules participate in import resolution and type checking.
- Interface modules do not emit executable bytecode by themselves.
9.2 Allowed role
At minimum, an interface module may provide:
- exported names,
- types,
- enums,
- host owners,
- method signatures,
- compile-time metadata such as canonical host-binding attributes.
This list fixes the currently required declarative role of interface modules, but does not by itself freeze the final complete declaration set allowed in interface-module mode.
An interface module is not runtime code.
9.3 Interface-module restrictions
At minimum, an interface module MUST remain declarative.
Rules:
- Interface modules MUST NOT contain top-level executable statements.
- Interface modules MUST NOT require runtime initialization.
- Interface modules MUST NOT introduce executable method bodies that would emit bytecode.
declare hostis permitted only in reserved stdlib/toolchain interface modules.- Reserved attributes such as
[Host(...)]are permitted only where another specification explicitly allows them.
9.4 Example interface module
Illustrative stdlib interface module:
declare enum color(red, green, blue);
declare host Gfx {
[Host(module = "gfx", name = "draw_pixel", version = 1)]
fn draw_pixel(x: int, y: int, c: color);
}
Rules:
- This module is valid only in a reserved stdlib/interface-module context.
- It contributes compile-time symbols and metadata.
- It does not produce executable bytecode by itself.
Another valid reserved stdlib interface module in stdlib line 1 is the sprite-composition surface:
declare host LowComposer {
[Host(module = "composer", name = "emit_sprite", version = 1)]
[Capability(name = "gfx")]
fn emit_sprite(
glyph_id: int,
palette_id: int,
x: int,
y: int,
layer: int,
bank_id: int,
flip_x: bool,
flip_y: bool,
priority: int
) -> int;
}
10. Compiler Loading of the Stdlib Environment
The compiler loads the stdlib environment from the stdlib line selected by the root project.
Required model:
- Read the root
prometeu.json. - Determine the effective stdlib major line.
- Mount or select the matching stdlib environment.
- Expose its reserved project spaces such as
@sdk:*and@core:*. - Load interface modules from that environment on demand during import resolution.
- Parse those modules with the ordinary PBS parser.
- Validate them under interface-module semantic rules.
- Populate the compiler's symbol graph from their exported declarations and attributes.
Rules:
- The compiler MUST behave as if it were loading real modules, not hardcoded symbol tables.
- The physical storage format of the stdlib environment is an implementation detail.
- The compiler MAY load the stdlib environment from disk, embedded resources, a virtual filesystem, or another implementation-defined source with equivalent behavior.
- For the Studio PBS frontend, embedding stdlib interface modules under frontend
resourcesis a valid implementation strategy.
11. Reserved Attributes and Metadata Lifecycle
11.1 General rule
Attributes are compile-time metadata, not runtime objects.
Rules:
- Attributes are parsed as part of the source module.
- Attributes participate in declaration validation and compiler metadata extraction.
- Attributes are not exported as ordinary values, types, or runtime-reflectable objects.
- Attributes do not automatically survive into bytecode, PBX, or runtime metadata.
11.2 Host attribute
The canonical reserved host-binding attribute is:
[Host(module = "gfx", name = "draw_pixel", version = 1)]
Rules:
Hostis valid only on a host method signature declared directly inside a reserved stdlib/interface-moduledeclare hostbody.Hostprovides the canonical host primitive identity used by compiler lowering.moduleandnameare string literals.versionis a positive integer literal.- The attribute surface itself is compile-time only.
11.3 Lowering effect
Although the attribute syntax itself is compile-time only, its semantic effect may be lowered.
Rules:
- The compiler consumes
Hostmetadata while resolving host-backed SDK members. - The compiler uses that metadata to emit runtime-facing host-binding declarations as defined by the Host ABI Binding specification.
- The compiler does not export the raw
[Host(...)]syntax into runtime as a source-level attribute object.
In other words:
- the attribute is compile-time metadata,
- the lowered host-binding declaration is runtime-facing artifact metadata,
- they are not the same thing.
12. Relationship to declare host
Rules:
declare hostremains reserved to SDK/toolchain-controlled modules.- Ordinary user-authored project modules do not declare canonical host bindings directly.
- User code consumes SDK exports through normal imports.
- SDK-facing surfaces such as
Gfx.draw_pixel(...)andComposer.emit_sprite(...)are resolved by the compiler against the selected stdlib environment. - Canonical host identity comes from reserved host-binding metadata such as
[Host(...)], not from the source spelling of the imported owner.
13. Project Publication and Distribution
Rules:
- Ordinary publication and dependency resolution operate at project granularity.
- A published project version contains one or more modules.
- Imports consume modules from a resolved project.
- The stdlib environment is distributed separately from ordinary project dependencies.
- The stdlib environment is selected by
stdlib, not bydependencies.
14. Non-Goals
- Making stdlib modules implicitly visible without
import. - Treating the stdlib as an ordinary dependency in the workspace graph.
- Allowing each dependency project to activate its own stdlib line.
- Hardcoding stdlib symbols directly into the compiler without a module model.
- Runtime reflection over source-level attributes.
15. Open Items Deferred
The following remain intentionally deferred:
- Exact on-disk distribution format of stdlib environment packs.
- Registry/publication protocol details for ordinary projects.
- Final diagnostics catalog for all import-resolution failures.
- Full list of declarations allowed inside interface modules beyond the already-fixed reserved host surfaces.
16. Current Decision Summary
The current PBS design direction is:
prometeu.jsondeclareslanguageandstdlibseparately.- A project is the unit described by
prometeu.jsonand selected bydependencies. - A module is the unit selected by
import. - Canonical module addresses use
@project:path/to/module. @sdk:*and@core:*are reserved stdlib project spaces.- The root project selects the effective stdlib line for the whole build.
- Dependency projects with a higher stdlib requirement than the root are rejected.
- Stdlib modules are loaded as PBS-like interface modules, not as ordinary dependencies.
- Interface modules are compile-time-only in packaging terms: they may carry declarative service facades with method bodies for source-level API ergonomics, but they still do not emit executable bytecode as standalone modules.
declare hostremains reserved to stdlib/toolchain interface modules.- Reserved attributes such as
[Host(...)]are compile-time metadata, not runtime objects. - The compiler consumes
Hostmetadata to produce runtime-facing host-binding artifacts defined elsewhere.