177 lines
6.6 KiB
Markdown
177 lines
6.6 KiB
Markdown
---
|
|
id: DEC-0004
|
|
ticket: pbs-low-level-asset-manager-surface
|
|
title: PBS Low-Level Asset Manager Surface for Runtime AssetManager
|
|
status: accepted
|
|
created: 2026-03-27
|
|
accepted: 2026-03-27
|
|
agenda: AGD-0008
|
|
plans: [PLN-0004]
|
|
tags: [compiler, pbs, runtime, asset-manager, host-abi, stdlib, asset]
|
|
---
|
|
|
|
## Decision
|
|
|
|
PBS SHALL expose the runtime asset low-level surface through a reserved host-backed owner named `LowAssets`.
|
|
|
|
The canonical v1 PBS declaration owner SHALL be:
|
|
|
|
```pbs
|
|
declare host LowAssets { ... }
|
|
```
|
|
|
|
This owner name is editorial PBS surface only.
|
|
It MUST NOT change the canonical runtime identities published by `../runtime`.
|
|
|
|
The low-level PBS asset surface SHALL bind to the current runtime syscall identities:
|
|
|
|
- `("asset", "load", 1)`
|
|
- `("asset", "status", 1)`
|
|
- `("asset", "commit", 1)`
|
|
- `("asset", "cancel", 1)`
|
|
|
|
The capability spelling for this surface SHALL be `asset`, in the singular:
|
|
|
|
```pbs
|
|
[Capability(name = "asset")]
|
|
```
|
|
|
|
PBS SHALL NOT publish `assets` as the capability string for this low-level surface.
|
|
|
|
For v1, the low-level PBS surface SHALL use raw `int` for:
|
|
|
|
- `asset_id`
|
|
- `slot`
|
|
- `handle`
|
|
- operation and lifecycle status values
|
|
|
|
The canonical illustrative shape is:
|
|
|
|
```pbs
|
|
declare host LowAssets {
|
|
[Host(module = "asset", name = "load", version = 1)]
|
|
[Capability(name = "asset")]
|
|
fn load(asset_id: int, slot: int) -> (status: int, loading_handle: int);
|
|
|
|
[Host(module = "asset", name = "status", version = 1)]
|
|
[Capability(name = "asset")]
|
|
fn status(loading_handle: int) -> int;
|
|
|
|
[Host(module = "asset", name = "commit", version = 1)]
|
|
[Capability(name = "asset")]
|
|
fn commit(loading_handle: int) -> int;
|
|
|
|
[Host(module = "asset", name = "cancel", version = 1)]
|
|
[Capability(name = "asset")]
|
|
fn cancel(loading_handle: int) -> int;
|
|
}
|
|
```
|
|
|
|
## Rationale
|
|
|
|
This decision locks the low-level PBS surface to the runtime contract that actually exists in the workspace on 2026-03-27.
|
|
|
|
The runtime side has already converged on:
|
|
|
|
- `asset.load(asset_id, slot) -> (status, handle)`
|
|
- `asset.status(handle) -> status`
|
|
- `asset.commit(handle) -> status`
|
|
- `asset.cancel(handle) -> status`
|
|
|
|
The earlier name-based low-level load path is no longer the active runtime contract.
|
|
PBS SHOULD therefore stop treating that retired shape as a first-class candidate.
|
|
|
|
`LowAssets` was chosen instead of `LowAsset` or `LowAssetManager` because:
|
|
|
|
- it reads naturally beside higher-level surfaces such as a future `Assets` facade;
|
|
- it matches the user-facing plurality of the domain without changing runtime ABI identities;
|
|
- it keeps the source declaration owner concise.
|
|
|
|
Raw `int` was chosen for v1 because:
|
|
|
|
- the runtime ABI is slot-based and already integer-shaped;
|
|
- the immediate need is to publish a stable low-level bridge, not a richer type taxonomy;
|
|
- delaying the SDK interface until nominal wrappers are designed would block spec and implementation progress without changing executable semantics.
|
|
|
|
Capability spelling remains singular `asset` because capability names are operational registry identities, not editorial surface names.
|
|
They MUST stay aligned with the runtime capability map.
|
|
|
|
## Technical Specification
|
|
|
|
### 1. Ownership And Binding
|
|
|
|
- PBS low-level asset access MUST be declared through `declare host LowAssets`.
|
|
- Each member MUST carry a canonical `[Host(module = "asset", name = "...", version = 1)]` attribute.
|
|
- Each member MUST carry `[Capability(name = "asset")]`.
|
|
- PBS compilers and loaders MUST treat `module`, `name`, `version`, argument slots, return slots, and capability spelling as runtime-facing operational identity.
|
|
|
|
### 2. ABI Shape
|
|
|
|
The required v1 members are:
|
|
|
|
1. `load(asset_id: int, slot: int) -> (status: int, loading_handle: int)`
|
|
2. `status(loading_handle: int) -> int`
|
|
3. `commit(loading_handle: int) -> int`
|
|
4. `cancel(loading_handle: int) -> int`
|
|
|
|
Normative ABI correspondence:
|
|
|
|
- `load` MUST lower to runtime syscall identity `("asset", "load", 1)` with `arg_slots = 2` and `ret_slots = 2`.
|
|
- `status` MUST lower to `("asset", "status", 1)` with `arg_slots = 1` and `ret_slots = 1`.
|
|
- `commit` MUST lower to `("asset", "commit", 1)` with `arg_slots = 1` and `ret_slots = 1`.
|
|
- `cancel` MUST lower to `("asset", "cancel", 1)` with `arg_slots = 1` and `ret_slots = 1`.
|
|
|
|
### 3. Value Semantics
|
|
|
|
- `asset_id` SHALL represent the runtime asset identity carried by `asset_table`.
|
|
- `slot` SHALL represent the target runtime slot index.
|
|
- `handle` SHALL represent the runtime load-operation handle returned by `load` when status is `OK`.
|
|
- PBS source signatures SHOULD use a non-keyword parameter label such as `loading_handle` for this value.
|
|
- status values SHALL remain raw integer domain values in the low-level surface for v1.
|
|
|
|
PBS low-level callers MUST NOT pass:
|
|
|
|
- `asset_name`
|
|
- `bank_type`
|
|
- any alternate symbolic asset reference directly to `LowAssets.load`
|
|
|
|
The runtime resolves bank kind from `asset_table` using `asset_id`.
|
|
PBS low-level surface MUST preserve that rule.
|
|
|
|
### 4. Relationship To Higher-Level Surfaces
|
|
|
|
- This decision defines only the low-level host-backed asset surface.
|
|
- It does NOT define the final author-facing asset API.
|
|
- Any future symbolic PBS asset surface, including `Addressable` or `assets.foo.bar` style references, MUST lower to `asset_id` before the final `LowAssets.load(...)` host call.
|
|
- A future `declare service Assets` MAY wrap `LowAssets`, but such facade MUST NOT alter the canonical host identities defined here.
|
|
|
|
### 5. Scope Boundary
|
|
|
|
This decision covers:
|
|
|
|
- the low-level owner name;
|
|
- capability spelling;
|
|
- canonical host bindings;
|
|
- raw value shape for v1.
|
|
|
|
This decision does NOT yet cover:
|
|
|
|
- nominal wrapper types for `AssetId`, `Handle`, or `SlotIndex`;
|
|
- enum surfaces for asset status values;
|
|
- `bank.info` / `bank.slot_info` integration;
|
|
- the author-facing symbolic assets surface from `AGD-0006`.
|
|
|
|
## Constraints
|
|
|
|
- PBS MUST stay aligned with the runtime capability registry and syscall registry as implemented in `../runtime`.
|
|
- PBS MUST NOT publish a plural capability string `assets` for this surface.
|
|
- PBS MUST NOT reintroduce a name-based low-level load contract into the canonical v1 PBS host surface.
|
|
- Any future editorial refinement to stronger low-level types MUST preserve the same runtime syscall identities unless a new decision explicitly revises this one.
|
|
- Plans and implementation derived from this decision MUST propagate updates to PBS specs and stdlib resources before introducing user-facing wrappers.
|
|
|
|
## Revision Log
|
|
|
|
- 2026-03-27: Initial accepted decision from AGD-0008.
|
|
- 2026-03-27: Linked execution plan PLN-0004.
|
|
- 2026-03-27: Refined illustrative PBS signatures to use named tuple returns and non-keyword handle labels without changing the locked runtime contract.
|