prometeu-runtime/docs/runtime/learn/historical-game-memcard-slots-surface-and-semantics.md

139 lines
4.8 KiB
Markdown

# Historical Snapshot - Game Memcard Slots Surface and Semantics
Status: historical snapshot in `learn`, not normative.
Current normative anchors:
- [`../specs/08-save-memory-and-memcard.md`](../../specs/08-save-memory-and-memcard.md)
- [`../specs/16-host-abi-and-syscalls.md`](../../specs/16-host-abi-and-syscalls.md)
- [`../specs/16a-syscall-policies.md`](../../specs/16a-syscall-policies.md)
- [`mental-model-save-memory-and-memcard.md`](mental-model-save-memory-and-memcard.md)
- [`mental-model-status-first-and-fault-thinking.md`](mental-model-status-first-and-fault-thinking.md)
## Status
Accepted
## Context
Games need predictable, portable persistence for save/config/blob data without broad filesystem access.
Agenda `013-game-memcard-slots-surface-and-semantics.md` consolidated the product inputs:
- `game` uses `32` slots per game;
- maximum payload per slot is `32KB`;
- the game accesses only slots owned by its own `app_id`;
- persistence is explicit, with atomic `commit` per slot;
- save copy/export/import happens outside the game (Hub/OS).
This decision closes the v1 contract for the `game` profile while using decision `003` as the byte data plane.
## Decision
### 1. Base capacity and ownership contract
- each game has exactly `32` logical slots (`0..31`);
- each slot offers up to `32 * 1024` bytes of usable payload;
- userland access is restricted to the `app_id` that owns the loaded cart;
- there is no path-based access for games in v1.
### 2. Minimum memcard surface (status-first)
- `slot_count() -> (status:int, count:int)`
- `slot_stat(slot:int) -> (status:int, state:int, used_bytes:int, generation:int, checksum:int)`
- `slot_read(slot:int, buf:HeapRef<Bytes>, offset:int, max_bytes:int) -> (status:int, bytes_read:int)`
- `slot_write(slot:int, buf:HeapRef<Bytes>, offset:int, len:int) -> (status:int, bytes_written:int)`
- `slot_commit(slot:int) -> status:int`
- `slot_clear(slot:int) -> status:int`
Rules:
- `status` is always the first return value;
- byte operations use `HeapRef<Bytes>` plus an explicit window (`offset`, `max_bytes`/`len`);
- shape follows the policy in `16a`.
### 3. Runtime-owned digital envelope per slot
Each slot keeps canonical runtime-owned metadata:
- owning `app_id`;
- `slot_index`;
- `save_uuid`;
- `generation`;
- `payload_size`;
- `checksum`;
- `state` (`EMPTY`, `STAGED`, `COMMITTED`, `CORRUPT`).
`generation` and `checksum` are not manually controlled by userland:
- `generation` increments on each successful `slot_commit`;
- `checksum` is recalculated by the runtime on the persisted payload.
### 4. Visual envelope for Hub/OS
The slot exposes visual metadata for UX outside the game:
- `label`;
- `subtitle`;
- `updated_at` (or equivalent logical counter);
- `icon_ref` (static in v1, extensible to future animation).
### 5. Write policy and atomicity
- `slot_write` changes staging (it does not persist to the final destination);
- `slot_commit` applies per-slot atomic persistence;
- silent partial success is forbidden;
- on commit failure, it returns error `status` and preserves the atomicity invariant.
### 6. Fault-class boundary
`memcard(game)` follows `16a`:
- `Trap`: structural error (slot out of range, invalid/dead `HeapRef`, invalid window, invalid ABI shape);
- `status`: operational domain error;
- `Panic`: internal invariant break only.
Minimum domain status catalog:
- `OK`;
- `EMPTY`;
- `NOT_FOUND`;
- `NO_SPACE`;
- `ACCESS_DENIED`;
- `CORRUPT`;
- `CONFLICT`;
- `UNAVAILABLE`;
- `INVALID_STATE`.
### 7. Copy/export/import policy (outside the game)
- copy/export/import is a Hub/OS responsibility;
- the game does not receive an API to copy slots between apps;
- v1 validates ownership by `app_id` on import;
- conflict and corruption must be reflected through domain status and Hub UX.
### 8. Integration with host storage
- physical namespace isolated by `app_id`;
- physical per-slot representation is internal to the runtime/host;
- persistence should use an atomic strategy (temporary file + flush + platform-equivalent rename).
## Consequences
### Positive
- closes the `game` save contract without opening broad FS access;
- makes copy/export/import a system flow (Hub/OS), not a userland flow;
- standardizes slot integrity/versioning through `generation` + `checksum`.
### Costs
- requires per-slot staging/atomic commit implementation;
- requires explicit specification of the export/import format in Hub/OS;
- requires alignment with memcard and ABI specs.
## Required Follow-up
- agenda `013-game-memcard-slots-surface-and-semantics.md` should be considered closed and removed;
- `specs/08-save-memory-and-memcard.md` should absorb this contract (`32 x 32KB`, slots by `app_id`, atomic commit);
- `specs/16-host-abi-and-syscalls.md` and `specs/16a-syscall-policies.md` should absorb the surface and fault/status matrix.