prometeu-studio/discussion/workflow/decisions/DEC-0004-pbs-low-level-asset-manager-surface.md

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.