874. Lesson identity
This lesson establishes how to decide what belongs in a save file, what should be discarded, what should be rebuilt as presentation, what should be recalculated, and which system owns each durable field.
875. Learning objective
After this lesson, you can create a save-state inventory for a multi-system game slice that classifies durable, transient, presentation, and derived state, assigns ownership to durable fields, and identifies the reconstruction path for non-durable state.
876. Why this matters
A save file is not a photograph of the running scene. It is a durable representation of the game state required to recreate a valid continuation. Saving transforms every participating system into a contract: fields need stable meanings, clear ownership, and a defined reconstruction path. If an AI-generated implementation serializes scene objects indiscriminately, it may preserve presentation details while losing the rules that make the game coherent.
877. Prior knowledge
You should already be able to identify system boundaries and contracts from Stage 2. In particular, this lesson builds on module 2.12 — Arrival is a contract, not a distance guess. You should be able to distinguish an authoritative gameplay condition from a presentation detail and from a value computed from other state.
878. Core concept
The core concept is the serialization boundary.
Persist only the durable state needed to restore the game contract. Transient state is temporary runtime state that may be discarded or resolved before saving. Presentation state is the visual or interface expression of other state. Derived state is calculated from authoritative facts or current rules. These categories require different treatment:
| Category | Meaning | Typical treatment |
|---|---|---|
| Durable state | Player or world facts that must survive a session boundary | Serialize explicitly |
| Transient state | Temporary runtime state that exists while an operation or interaction is in progress | Resolve, cancel, or discard; do not persist by default |
| Presentation state | Objects, references, animations, effects, and UI that express gameplay state | Rebuild or rebind after loading |
| Derived state | Values calculated from durable facts or current rules | Recompute; do not store as an independent authority |
Serialization is therefore not “save every variable.” It is the deliberate selection of the smallest stable representation that can restore the intended game state. A transaction that has not committed, a temporary interaction lock, or a cached target may be important while the game is running without being part of the durable contract.
879. Schema ownership
Every persisted field should have one owning system. The owner defines:
- The field's meaning.
- The valid range or allowed values.
- When the field changes.
- How the field is validated when loaded.
- How the field is used to reconstruct runtime state.
For example, an inventory system may own credits and items. A scene controller may display those values, but it should not become their save-state owner merely because it has access to the UI or scene nodes. A pending inventory transaction may belong to the inventory transaction service while it is active, but it is transient unless the game explicitly promises to resume that unfinished operation.
880. Mental model
Use the contract, runtime, reconstruction, derivation model:
DURABLE CONTRACT
↓ serialize
SAVE DATA
↓ load and validate
RUNTIME STATE
├── transient operations: resolve or discard
├── presentation: rebuild or rebind
└── derived values: recalculate from durable facts
For each candidate field, ask four questions:
| Question | Decision |
|---|---|
| Must this fact remain true after closing and reopening the game? | If yes, it may belong in durable state. |
| Is it only needed while an operation or interaction is in progress? | If yes, it is probably transient and should be resolved or discarded. |
| Does it exist to display or animate another state? | If yes, it is presentation and should be rebuilt or rebound. |
| Can it be calculated from saved facts and current rules? | If yes, it is derived and should be recomputed. |
For every durable field, also ask: which system defines its meaning and valid changes? That system owns the field.
This model prevents two opposite errors. Saving too little causes lost progress or inconsistent rules. Saving too much creates duplicated authorities, stale values, and fragile coupling to the current scene structure.
881. Concrete example
Consider a small slice with a player, an inventory, and a gate that opens after the player obtains a pass.
| Candidate value | Classification | Owner | Load behavior |
|---|---|---|---|
| Player's world position | Durable, if position is part of the continuation contract | Player/world state | Restore after the destination scene is ready |
hasPass |
Durable | Inventory or progression system | Restore, then notify dependent systems |
| Pending purchase awaiting confirmation | Transient | Inventory transaction system | Resolve before saving, or cancel and discard |
| Gate object reference | Presentation | Gate controller | Find or create the gate in the loaded scene |
| Gate animation progress | Presentation | Gate controller | Reapply the open or closed state |
| Number of open gates | Derived | Gate or progression rules | Recompute from authoritative world facts |
| Player UI icon for the pass | Presentation | UI system | Rebuild from inventory state |
The save file does not need to contain a serialized gate object, an animation track, a UI node, or an unfinished purchase operation. It needs the durable facts that determine whether the gate should be open and where the player should continue. The gate controller and UI then reconstruct their presentation from those facts.
A subtle decision remains: is the player's exact position durable? If the game promises continuation from the exact location, save it. If the game promises only a checkpoint or safe-room restart, save the checkpoint identity instead. The answer comes from the game contract, not from whichever variable is easiest to serialize.
882. Common mistake
The common mistake is treating every non-durable value as the same kind of state, or treating the current scene tree as the save schema.
A pending transaction is not the same as a HUD label. The transaction is transient process state; the label is presentation. Neither should automatically become save data. A scene also contains temporary objects, engine references, cached values, and visual state. It is an implementation arrangement, not necessarily the durable contract.
Another mistake is saving both an authoritative value and its derivative—for example, saving hasPass and openGateCount—without defining which one wins if they disagree. On load, duplicated authorities can produce a game that looks correct while violating its own rules.
883. Guided practice
Create a save-state inventory for this multi-system slice:
- The player can carry credits and items.
- A contract is active or inactive.
- The current destination is one of three regions.
- A door presentation changes when the contract is complete.
- The HUD displays credits, the active contract, and the current region name.
- The door's open animation and the HUD labels are created during runtime.
- An inventory transaction can remain pending briefly before credits and items are committed.
Make a table with these columns:
Candidate field | Durable / Transient / Presentation / Derived | Owning system | Save, resolve, discard, or reconstruct? | Reason
Classify at least these candidates:
creditsitemscontractCompletedcurrentRegionIdpendingInventoryTransaction- door object reference
- door animation progress
- HUD credit text
- HUD region label
- number of completed contracts
For pendingInventoryTransaction, make an explicit decision: identify whether the transaction must be committed or canceled before saving, and explain why the unfinished operation itself is not automatically durable state. Keep the committed result—such as updated credits or items—in the durable contract if the game promises that result will survive.
Then make one explicit decision about the player's location: choose either playerPosition or checkpointId as the durable representation. State what continuation promise justifies your choice.
Do not begin by listing variables from a scene. Begin with the facts the player expects to survive closing and reopening the game. If a value can be calculated from another saved value, mark it as derived and identify its source.
884. Validation / evidence
Your inventory is valid when it provides visible evidence of all five decisions below:
- Every candidate field has exactly one classification among durable, transient, presentation, and derived.
- Every durable field has one owning system.
- Every transient field has a resolve, cancel, or discard decision.
- Every presentation value has a reconstruction or rebinding path.
- Every derived value names the authoritative data from which it is calculated.
As a final consistency check, remove all transient and presentation fields from your proposed save data. Explain how the game would recreate the door and HUD, and how it would handle the pending inventory transaction, using the remaining durable contract and derived calculations. If you cannot explain that reconstruction, the boundary is incomplete.
885. Key takeaways
- A save file represents durable game facts, not a captured scene tree.
- Transient operations should be resolved, canceled, or discarded unless the game explicitly promises to resume them.
- Runtime objects and presentation should be rebuilt from the saved contract.
- Derived values should be recomputed from authoritative state rather than saved as competing authorities.
- Each persisted field needs a clear owning system and a defined meaning.
886. Next lesson
Continue to 2.13 L2 — Restore systems in a deliberate order.
887. Persistence (fix-save-roundtrip)
Open academy-fixtures/labs/save-roundtrip. Run node run.mjs. Inspect which fields are durable. Presentation and lastFeedback are not a second save authority.
888. Handoff contracts (fix-handoff-contracts)
Open academy-fixtures/labs/handoff-contracts. Run node run.mjs. Record inputs, outputs, owner, invariants, failure (illegal write), validation. Then fix-save-roundtrip: academy-fixtures/labs/save-roundtrip → node run.mjs.
889. Knowledge check
Answer these items for yourself before reading the answers.
Which value is the best candidate for durable save state?
Show answer and feedback
Answer: The player's earned credits
Why: Earned credits are a durable gameplay fact that may need to survive closing and reopening the game. HUD text, object references, and animation details are runtime presentation.
What should normally happen to a value that can be calculated from authoritative saved facts?
Show answer and feedback
Answer: Recompute it after loading.
Why: Derived values should be recomputed from authoritative data. Saving them independently can create stale or conflicting authorities.
Who should own a persisted field?
Show answer and feedback
Answer: The system that defines its meaning, valid changes, and reconstruction rules
Why: Ownership belongs to the system that defines the field's contract. Displaying or writing a value does not make a scene or UI its authority.
What determines whether to save an exact player position or a checkpoint identifier?
Show answer and feedback
Answer: The continuation promise made by the game
Why: The save representation must match what the game promises after loading. Exact continuation requires a position; checkpoint continuation requires a checkpoint identity.