ADR-001: Caller-owned fixed-capacity world
Date: 2026-07-18
Status: Accepted
Context
The architecture for v0.1.0 left the world memory and lifecycle strategy
open in section 9.2. Epic E02 requires one owner for authoritative state, no hidden global mutable
world, no dynamic allocation inside Pet Core, and a compile-time maximum for every collection.
Three candidate strategies were available: caller-owned storage, Core-allocated opaque state, and caller-supplied storage passed as a buffer and size.
Decision
PetWorld is a complete public structure. The caller declares the storage and chooses where it
lives, and pet_world_init writes into that storage.
Every bounded collection has a capacity macro, so the size of a world is fixed when the library is compiled. Pet Core never allocates a world, never frees one, and retains no pointer to one.
The pet is stored inline in its world rather than referenced, so its lifetime is exactly the lifetime of the world that owns it.
Consequences
Several worlds may exist independently because nothing is shared between them. A world can live on the stack, in static storage, or inside memory the caller obtained elsewhere, which suits both hosted and embedded environments.
Callers can see the field layout. The header states that fields are visible for sizing and placement rather than as a stable interface, and later PBIs add operations that read state without exposing mutable pointers into nested storage.
Changing a capacity macro changes the size of PetWorld, so it is a recompilation for every caller.
The v0.1.0 measurements on Linux x86-64 are 48 bytes for PetWorld, 40 bytes for PetEntity, and
8 bytes for PetWorldConfig, with no temporary Core storage beyond the parameters of an operation.
These figures are the measurement taken when this decision was accepted. Later work adds persistent
fields, so the current measurement lives in the storage section of the architecture. The world clock
added by ADR-002 is the first such change.
A world declared without an initialiser holds indeterminate storage. PET_WORLD_INITIALISED gives
initialisation a recognisable marker rather than a boolean flag that cannot be distinguished from
unwritten memory.
Alternatives considered
Core-allocated opaque state. Hides the layout and keeps the header stable, but requires an
allocator or an arena inside Pet Core. E02 and SPEC-NFR-002
exclude this.
Caller-supplied buffer and size. Keeps the layout opaque without allocating, but adds an alignment and size contract to every operation and needs runtime validation that a fixed structure gets from the compiler. The extra contract has no benefit while one world holds one pet.
References
- Architecture for v0.1.0
- Epics
- Product backlog items
- ADR-002, which stores time state in the world
PBI-014