# 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:gfx`, - compile-time reserved metadata attached to those reserved modules, - and interface-only service facades that wrap host surfaces for source ergonomics. 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. ## 2. Scope This document defines: - the role of `language` in `prometeu.json`, - the role of `stdlib` in `prometeu.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(...)]`. This document does not define: - PBX binary layout, - loader-side syscall resolution, - cartridge capability policy, - package registry protocol details, - runtime reflection over attributes. ## 3. Core Terms ### 3.1 Project A project is the unit described by `prometeu.json`. Rules: - A project has a `name`, `version`, `language`, `stdlib`, and `dependencies`. - 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 `.pbs` source 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: ```text @project:path/to/module ``` Rules: - `project` identifies the owning project space. - `path/to/module` identifies 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: ```json { "name": "main", "version": "1.0.0", "language": "pbs", "stdlib": "1", "dependencies": [ { "name": "dep1", "version": "1.0.0" } ] } ``` Rules: - `name` identifies the project. - `version` identifies the project version. - `language` identifies the frontend language. - `stdlib` identifies the selected stdlib major line. - `dependencies` declare ordinary project dependencies only. ### 4.2 `language` Rules: - `language` selects the compiler frontend. - All projects in one resolved workspace MUST use the same `language`. - Unknown `language` values are compile-time errors. ### 4.3 `stdlib` Rules: - `stdlib` is required in every manifest. - `stdlib` uses major-only version syntax in v1. - The manifest surface for `stdlib` is 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 `stdlib` internally to an integer major version. Diagnostics: - Missing `stdlib` is a manifest error. - Invalid major-only format is a manifest error. ## 5. Ordinary Dependencies vs Stdlib Environment ### 5.1 Ordinary dependencies Rules: - `dependencies` model 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. - `dependencies` do 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: ```pbs import { Gfx, color } from @sdk:gfx; let c: color = color.red; Gfx.draw_pixel(1, 1, c); ``` Rules: - `Gfx` is not implicitly in scope. - `Gfx` becomes visible only through `import`. - The compiler accepts that import because the selected stdlib environment exposes `@sdk:gfx`. ## 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: - `stdlib` on 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: - `R` be the root project's `stdlib` major, - `D` be a dependency project's `stdlib` major. Rules: - If `D > R`, dependency resolution MUST fail with a deterministic compile-time error. - If `D <= R`, dependency resolution MAY proceed. - `D <= R` does 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"`, dependency `stdlib = "2"`: error. - root `stdlib = "2"`, dependency `stdlib = "1"`: allowed. - root `stdlib = "1"`, dependency `stdlib = "1"`: allowed. ## 8. Import Resolution ### 8.1 Resolution sources The compiler resolves imports against exactly two sources: 1. the selected stdlib environment, 2. 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: ```pbs import { X } from @project:path/to/module; ``` the compiler MUST: 1. parse the project space and module path, 2. determine whether the project space is reserved, 3. if reserved, resolve the module from the selected stdlib environment, 4. otherwise, resolve the module from the root project or its dependency graph, 5. load the target module, 6. 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 `.pbs` modules 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 host` is 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: ```pbs 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. ## 10. Compiler Loading of the Stdlib Environment The compiler loads the stdlib environment from the stdlib line selected by the root project. Required model: 1. Read the root `prometeu.json`. 2. Determine the effective stdlib major line. 3. Mount or select the matching stdlib environment. 4. Expose its reserved project spaces such as `@sdk:*` and `@core:*`. 5. Load interface modules from that environment on demand during import resolution. 6. Parse those modules with the ordinary PBS parser. 7. Validate them under interface-module semantic rules. 8. 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 `resources` is 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: ```pbs [Host(module = "gfx", name = "draw_pixel", version = 1)] ``` Rules: - `Host` is valid only on a host method signature declared directly inside a reserved stdlib/interface-module `declare host` body. - `Host` provides the canonical host primitive identity used by compiler lowering. - `module` and `name` are string literals. - `version` is 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 `Host` metadata 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 host` remains 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(...)` 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 by `dependencies`. ## 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: 1. Exact on-disk distribution format of stdlib environment packs. 2. Registry/publication protocol details for ordinary projects. 3. Final diagnostics catalog for all import-resolution failures. 4. 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: 1. `prometeu.json` declares `language` and `stdlib` separately. 2. A project is the unit described by `prometeu.json` and selected by `dependencies`. 3. A module is the unit selected by `import`. 4. Canonical module addresses use `@project:path/to/module`. 5. `@sdk:*` and `@core:*` are reserved stdlib project spaces. 6. The root project selects the effective stdlib line for the whole build. 7. Dependency projects with a higher stdlib requirement than the root are rejected. 8. Stdlib modules are loaded as PBS-like interface modules, not as ordinary dependencies. 9. 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. 10. `declare host` remains reserved to stdlib/toolchain interface modules. 11. Reserved attributes such as `[Host(...)]` are compile-time metadata, not runtime objects. 12. The compiler consumes `Host` metadata to produce runtime-facing host-binding artifacts defined elsewhere.