Pet architecture
| Document version | Date | Summary |
|---|---|---|
| v1 | 2026-07-17 | Initial product architecture baseline |
Status: Draft
Scope: Product level architecture
Related documents: Product specification, milestones, and version architecture policy
Template: arc42
1. Introduction and goals
1.1 Purpose
This document describes the long term architecture of Pet. It defines stable system boundaries, responsibilities, dependency rules, and quality tactics that apply across product versions.
Version specific architecture documents describe how one product release realises this architecture. They name concrete libraries, executable targets, persistence formats, supported adapters, deployment environments, and verification evidence.
1.2 Architecture goals
- keep pet behaviour independent of presentation technology
- support desktop and future embedded frontends without separate domain implementations
- keep time, randomness, input, and external events controllable in tests
- allow physical and digital integrations through adapters
- preserve local ownership and offline operation
- keep the Pet Core portable across hosted and embedded environments
- use useful functional programming principles without ignoring C and embedded constraints
- prevent platform details from entering the Pet Core
- make the codebase understandable through explicit boundaries
1.3 Documentation model
This file is the general architecture baseline. Files under docs/arch/arch-vx.y.z.md describe individual product releases.
Product versions follow Semantic Versioning 2.0.0. The file name identifies the product version. The revision table inside each file identifies the document revision.
docs/arch/
README.md
architecture.md
arch-v0.1.0.md
arch-v0.2.0.md
arch-v1.0.0.mdEvery architecture document follows the mandatory version architecture policy and the arc42 top level structure.
1.4 Decision ownership
The product specification defines required outcomes. This document defines shared architecture rules. Version documents define concrete realisations. Important choices with meaningful alternatives belong in Architecture Decision Records.
flowchart TD S[Product specification] G[General architecture] V[Version architecture] A[Architecture decisions] W[Implementation work] S --> G G --> V A --> V V --> W W --> A
2. Architecture constraints
2.1 Product constraints
- basic pet behaviour and local persistence work without a network connection
- absence does not permanently harm the pet
- one world contains one active pet during the initial versions
- networking, pet transfer, and multiple pet interaction are deferred beyond V1
- final hardware is not required to validate the initial software product
- AI is not required for the core experience
2.2 Core constraints
- the Pet Core is written in portable ISO C99
- required Core behaviour does not depend on compiler extensions
- the Core remains suitable for hosted and embedded C environments
- the Core does not depend on SDL or another frontend library
- the Core does not directly access hardware sensors
- the Core does not directly call Git, network, mobile, or cloud APIs
- the Core does not depend on the actual system clock
- the Core does not require a graphical environment
- the Core does not require a filesystem, network stack, or thread runtime
- authoritative world state has one owner
- frontends and adapters do not mutate authoritative state directly
- missed time processing remains bounded
2.3 Boundary constraints
- external physical and digital input enters through adapters
- external input is validated before it affects domain state
- presentation state is derived and read only
- storage access remains outside the Core
- platform support claims distinguish design intent from verified support
2.4 Language constraints
- code and developer documentation use British English
- C domain APIs use the
petprefix - detailed implementation conventions belong in code rules
3. System scope and context
3.1 Product context
Pet is a local companion product. A user interacts with a pet through a frontend. The product may receive optional information from physical sensors or digital services through adapters.
The initial product runs locally and does not require an account, cloud service, peer discovery, or another pet.
flowchart LR U[User] P[Pet system] E[Physical environment] D[Digital sources] L[Local storage] U <--> P E --> P D --> P P <--> L
3.2 External actors
User
Observes and interacts with the pet.
Physical environment
Provides optional observations through sources such as proximity, motion, orientation, touch, and ambient light sensors.
Digital source
Reports optional activities or events. Examples include a Git hook, focus tool, reading service, and local script.
Local storage
Retains pet state through a platform facility. The storage mechanism does not define domain behaviour.
3.3 Technical context
flowchart TD H[Host application] C[Pet Core] F[Frontend] A[Adapters] S[Storage] F <--> H A --> H S <--> H H <--> C
The host composes one Pet Core with the components available in its environment. A release may omit a frontend, adapters, or durable storage when its declared scope does not require them.
3.4 Initial system boundary
V0 and V1 do not require:
- cloud services
- pet transfer between devices
- local network discovery
- peer interaction
- shared household simulation
- multiple active pets in one world
These features may be considered after V1 without adding premature assumptions to the initial architecture.
4. Solution strategy
4.1 Core and boundaries
The system is divided into a platform independent Pet Core and effectful boundary components. A host application composes the active components.
flowchart TD H[Host application] C[Pet Core] F[Frontend] A[Adapters] S[Storage] H --> C H --> F H --> A H --> S F --> H A --> H C --> H
4.2 Functional core and imperative shell
The architecture follows a functional core and imperative shell strategy. The Pet Core contains deterministic state transitions where practical. The host, frontends, adapters, and storage implementations perform platform effects.
flowchart LR E[External effects] H[Imperative host] C[Functional Core] O[Outputs and effects] E --> H H --> C C --> H H --> O
Functional principles guide the design. They do not require copying large world state or avoiding all mutation. Controlled in place updates may be used when they provide clearer ownership and lower memory cost.
4.3 Main strategies
- represent user intent as semantic actions
- represent external information as semantic events or environment state
- expose read only presentation state to frontends
- inject time and randomness into Core operations
- keep authoritative state inside the Core boundary
- isolate persistence through explicit save and restore operations
- keep frontend and adapter capabilities optional
- validate all data that crosses a boundary
- keep effects at system boundaries
- keep Core transitions deterministic where practical
- make mutation local, explicit, and owned
- add abstractions only when a product version requires them
5. Building block view
5.1 Level 1 building blocks
flowchart LR subgraph Boundary F[Frontend] A[Adapter] S[Storage] end H[Host application] C[Pet Core] F <--> H A --> H S <--> H H <--> C
5.2 Pet Core
The Pet Core is the platform independent domain and simulation layer. It owns authoritative world state and applies valid input to that state.
Responsibilities include:
- world lifecycle and validation
- pet identity and current state
- time based updates
- semantic action and event handling
- mood and autonomous behaviour
- formative events and identity development
- bounded maturity
- progression, memories, traits, and discoveries
- presentation state generation
- persistence semantics
The Core does not own:
- graphics or audio devices
- platform input mappings
- sensor drivers and calibration
- Git hooks and service clients
- file paths and platform storage APIs
- actual wall clock access
- networking and peer discovery
5.3 Host application
The host application is the composition and orchestration boundary for one executable environment.
Responsibilities may include:
- creating and destroying Core state
- obtaining time from the platform
- collecting frontend actions
- polling or receiving adapter output
- delivering validated input to the Core
- requesting presentation state
- invoking the active frontend
- coordinating save and restore
- defining application lifecycle
The host is the imperative shell. It must not become a second domain layer.
5.4 Frontend
A frontend presents the pet and accepts direct user interaction in a particular environment.
Examples include SDL, OLED, e ink, mobile, web, and headless diagnostic frontends.
A frontend may:
- render presentation state
- map platform input to semantic actions
- report presentation and input capabilities
- provide platform specific menus and accessibility features
A frontend must not:
- own authoritative pet state
- define domain progression rules
- modify memories, traits, or mood directly
- assume every frontend has the same capabilities
5.5 Adapter
An adapter translates an external physical or digital source into semantic input understood by the host and Core.
Candidate physical sources include proximity, acceleration, orientation, touch, and ambient light. Candidate digital sources include Git hooks, focus tools, reading services, mobile activity sources, and local scripts.
The architecture does not yet require separate physical and digital interfaces. Their first interfaces will be based on observed requirements.
Adapters own source specific concerns such as drivers, calibration, filtering, authentication, event grouping, rate limiting, and semantic conversion.
5.6 Storage
Storage connects persistence data to a platform facility such as a local file, embedded flash, browser storage, or test buffer.
Storage owns platform access, atomic replacement where supported, platform errors, and storage location policy. It does not interpret pet behaviour.
5.7 Dependency rules
Source dependencies point towards the Pet Core. The Core does not include or link against frontend, adapter, storage, or host implementation code.
flowchart TD APP[Host application] FE[Frontend implementation] AD[Adapter implementation] ST[Storage implementation] CORE[Pet Core] APP --> CORE APP --> FE APP --> AD APP --> ST FE -. no dependency .-> CORE AD -. no dependency .-> CORE ST -. no dependency .-> CORE
- Core code depends only on approved ISO C99 facilities and Core owned modules
- frontend implementations depend on frontend contracts and platform libraries
- adapter implementations depend on adapter contracts and source libraries
- storage implementations depend on storage contracts and platform facilities
- the host may depend on all components required for composition
- tests may replace effects with controlled implementations
- C++ hosts may consume the C API through a compatible language boundary
5.8 Core data model
Exact C structures belong in version architecture documents. The stable conceptual relationships are:
classDiagram class World { time environment progression } class Pet { identity current state maturity } class Memory class Trait class Discovery World *-- Pet Pet *-- Memory Pet *-- Trait World *-- Discovery
Initial versions contain one active Pet in one World.
5.9 Authoritative and derived data
Authoritative state is the minimum state required to continue the pet consistently. Derived state is recalculated from authoritative state where practical.
Presentation state is always derived and must not be written back as domain state.
flowchart LR A[Authoritative world] U[Core update] P[Presentation state] R[Frontend render] A --> U U --> A A --> P P --> R
6. Runtime view
6.1 Normal application update
sequenceDiagram participant Platform participant Host participant Core participant Frontend Platform->>Host: time input Frontend->>Host: semantic actions Host->>Core: actions and elapsed time Core->>Core: update world Host->>Core: request presentation state Core-->>Host: presentation state Host->>Frontend: draw state
6.2 Adapter input
sequenceDiagram participant Source participant Adapter participant Host participant Core Source->>Adapter: source data Adapter->>Adapter: validate and translate Adapter->>Host: semantic event Host->>Core: deliver event Core->>Core: apply domain rules
6.3 Save and restore
sequenceDiagram participant Host participant Core participant Storage Host->>Core: request persistence data Core-->>Host: validated save payload Host->>Storage: write payload Storage-->>Host: result Host->>Storage: read payload Storage-->>Host: stored payload Host->>Core: restore candidate Core-->>Host: accepted or rejected
Restore is transactional from the perspective of active world state. Invalid input does not leave a partially restored world.
6.4 Missed time handling
The host supplies current time or elapsed duration. The Core performs a bounded summary transition instead of replaying every missed update.
flowchart LR L[Last saved time] N[Current time] B[Bounded transition] W[Updated world] L --> B N --> B B --> W
7. Deployment view
Concrete deployment targets belong in version architecture documents. The general architecture supports hosted and embedded compositions without requiring both in every release.
7.1 Hosted pattern
flowchart TD subgraph Hosted process H[Host application] C[Pet Core] F[Optional frontend] S[Local storage] end H --> C H --> F H --> S
7.2 Embedded pattern
flowchart TD subgraph Physical device EH[Embedded host] EC[Pet Core] EF[Display frontend] PA[Physical adapters] end EH --> EC EH --> EF EH --> PA
A version may provide no visual frontend, one frontend, or multiple frontends. Its version architecture records the concrete composition and verified toolchains.
Networking is not implied by multiple deployment patterns.
8. Crosscutting concepts
8.1 Time
Time enters the Core through explicit input. Domain code does not assume that time is monotonic, accurate, or unchanged by time zone adjustments.
8.2 Randomness
Randomness is controllable and reproducible in tests. Persisted state contains enough information to continue behaviour consistently when required by the selected model.
8.3 Validation and error handling
Every public boundary validates ranges, identifiers, collection sizes, enum values, and payload structure before changing authoritative state.
Expected failures are represented explicitly. Boundary failures are not converted into silent domain changes.
8.4 Ownership and memory
Every allocation and resource has a clear owner. Frontends and adapters do not retain mutable Core pointers unless an explicit contract permits it.
Core operations have bounded work. The architecture does not require one allocation strategy for every platform. A version may use caller owned memory, fixed capacity storage, an injected allocator, or another documented strategy.
Heap allocation remains explicit and replaceable where required by a supported target. Large state copies are not introduced only to imitate immutability.
8.5 Environment capabilities
A host may describe the capabilities available in its environment. The Core may use this information to avoid selecting interactions that cannot be represented or completed.
Candidate capabilities include input methods, display properties, audio, proximity, motion, orientation, touch, ambient light, and digital activity input.
flowchart TD C[Capability description] W[World context] R[Behaviour selection] O[Supported outcome] C --> R W --> R R --> O
Capabilities indicate availability. They do not expose platform APIs to the Core.
8.6 Persistence
The Pet Core owns persistence semantics. The storage boundary owns platform access.
Persisted formats support format identification, validation before activation, safe rejection, bounded payloads, explicit time treatment, and deterministic round trip tests where applicable.
Version documents record the selected format and compatibility promise.
8.7 Logging and diagnostics
Logging is a host concern. The Core may produce structured diagnostic information through an explicit boundary but does not depend on one logging backend.
8.8 Privacy
Adapters collect the minimum information required to create a semantic event. Raw source data is not retained by default when the domain needs only a derived event.
8.9 Functional design
Core behaviour is expressed as explicit state transitions. Time, randomness, actions, events, and capabilities enter through parameters or owned context. Results and requested effects leave through explicit return values or output structures.
The design prefers deterministic functions, immutable configuration, explicit ownership, narrow transformations, decision and effect separation, derived data, and exhaustive domain handling.
The design does not require copying the complete world, allocating a new object for every transition, removing useful local mutation, or imitating a purely functional language at the cost of embedded suitability.
8.10 Portability
ISO C99 is the Core language baseline. C99 is necessary but not sufficient. The Core also avoids assuming an operating system, filesystem, network stack, thread runtime, hardware SDK, or complete hosted C library.
Platform claims use these levels:
- portable by design: known platform dependencies are avoided
- build tested: compiled with a named hosted compiler and configuration
- cross compile tested: compiled with a named embedded toolchain
- runtime tested: executed and verified on a named target
Each version architecture records its verified support level.
9. Architecture decisions
9.1 Accepted decisions
- Pet Core owns authoritative world state
- frontends consume derived presentation state
- direct user input becomes semantic actions
- external physical and digital input enters through adapters
- storage access remains outside the Core
- time and randomness are explicit and testable
- Pet Core uses ISO C99
- the design follows functional core and imperative shell
- functional principles permit controlled local mutation
- product releases follow Semantic Versioning 2.0.0
- one host composes active components
- initial versions contain one pet in one world
- networking and pet transfer are deferred beyond V1
9.2 Open decisions
- whether physical and digital adapters need separate interfaces
- the exact boundary between serialisation and storage
- the initial source directory and library layout
- the initial update model and timing units
- the representation of presentation state
- the persistence format
- the maturity and formative event data model
- the capability description format
- allocation strategy for each supported environment
- the first embedded cross compilation target
Resolved choices with meaningful alternatives receive an Architecture Decision Record.
9.3 Architecture deviations
The general architecture has no deviations from itself. Version documents record any accepted deviation from this baseline.
10. Quality requirements
10.1 Requirement traceability
The product specification defines required quality outcomes. This architecture defines shared tactics. Version architecture documents record verification evidence.
| Requirement | Architecture tactics | Verification location |
|---|---|---|
| SPEC-NFR-001 | ISO C99 Core, inward dependencies, explicit platform boundaries | Version platform matrix |
| SPEC-NFR-002 | Bounded updates, explicit ownership, replaceable allocation | Version limits and tests |
| SPEC-NFR-003 | Explicit time, randomness, input, storage, and capabilities | Automated tests |
| SPEC-NFR-004 | Boundary validation and transactional restore | Negative and fault tests |
| SPEC-NFR-005 | Bounded missed time and adapter input | Performance checks |
| SPEC-NFR-006 | Explicit Core and boundary ownership | Dependency checks |
| SPEC-NFR-007 | SemVer, versioned persistence, version architecture | Release verification |
| SPEC-NFR-008 | Minimal semantic adapter data | Adapter review |
| SPEC-NFR-009 | Capability based frontend contracts | Frontend verification |
| SPEC-NFR-010 | British English and pet prefix | Review |
10.2 Architecture compliance
A version complies when:
- its architecture document follows README.md
- its release follows Semantic Versioning 2.0.0
- its Core has no forbidden platform dependencies
- its Core compiles as ISO C99 with documented toolchains
- authoritative state has one documented owner
- its frontend receives derived presentation data when a frontend exists
- external sources pass through adapters when adapters exist
- time and randomness can be controlled in tests
- save restoration validates before activation when persistence exists
- deviations are documented and justified
- quality requirements have verification evidence
- platform claims state their verified support level
Architecture compliance is checked during PBI review and before release completion.
11. Risks and technical debt
11.1 Current risks
- designing embedded abstractions before a real target exists
- assuming that C99 alone guarantees embedded portability
- making presentation state specific to the first visual frontend
- allowing adapter events to become an unrestricted command system
- creating excessive domain complexity before the pet experience is validated
- storing derived state that later becomes inconsistent
- confusing missed time progression with frame simulation
- introducing multiple pet assumptions too early
- combining document revisions with product versions
- applying functional rules in ways that increase memory cost or obscure ownership
11.2 Technical debt policy
Risks accepted by a release belong in its version architecture. Deferred implementation limitations belong in known limitations and link to a PBI where possible.
Architecture debt must not be hidden in progress notes or code comments.
12. Glossary
12.1 Terms
Pet Core: The platform independent domain and simulation layer.
Host application: The executable composition and orchestration boundary.
Frontend: A platform specific presentation and direct interaction component.
Adapter: A component that converts physical or digital source data into semantic Core input.
Storage: A platform component that retains and retrieves persistence data.
World: The authoritative state that contains the pet and its persistent context.
Presentation state: A read only view derived from the world for a frontend.
Semantic action: A platform independent representation of direct user intent.
Semantic event: A validated product level representation of external information.
Capability: A description of an available input, output, sensor, or integration feature.
Functional core: The deterministic domain area that transforms explicit input and owned state.
Imperative shell: The host and boundary area that performs platform effects.
Portable by design: A claim that known platform dependencies are avoided. It is not proof of target support.
Version architecture: The concrete architecture record for one product release.