# 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, offset:int, max_bytes:int) -> (status:int, bytes_read:int)` - `slot_write(slot:int, buf:HeapRef, 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` 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.