4.8 KiB
4.8 KiB
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/16-host-abi-and-syscalls.md../specs/16a-syscall-policies.mdmental-model-save-memory-and-memcard.mdmental-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:
gameuses32slots per game;- maximum payload per slot is
32KB; - the game accesses only slots owned by its own
app_id; - persistence is explicit, with atomic
commitper 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
32logical slots (0..31); - each slot offers up to
32 * 1024bytes of usable payload; - userland access is restricted to the
app_idthat 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:intslot_clear(slot:int) -> status:int
Rules:
statusis 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:
generationincrements on each successfulslot_commit;checksumis 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_writechanges staging (it does not persist to the final destination);slot_commitapplies per-slot atomic persistence;- silent partial success is forbidden;
- on commit failure, it returns error
statusand preserves the atomicity invariant.
6. Fault-class boundary
memcard(game) follows 16a:
Trap: structural error (slot out of range, invalid/deadHeapRef, 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_idon 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
gamesave 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.mdshould be considered closed and removed; specs/08-save-memory-and-memcard.mdshould absorb this contract (32 x 32KB, slots byapp_id, atomic commit);specs/16-host-abi-and-syscalls.mdandspecs/16a-syscall-policies.mdshould absorb the surface and fault/status matrix.