Lesson 238: Godot Playtest Save Isolation Receipt on BUILD_RECEIPT (2026)
Direct answer: Before you open a June playtest wave while fest_public stays live, file playtest_save_isolation_receipt_v1.json proving playtest and fest Godot builds use different user:// save roots, pass the installed Steam isolation matrix, and crosswalk save_slot_label_map per surface on BUILD_RECEIPT playtest_save_isolation. Distinct from Lesson 212 save slot labels (UI ↔ Cloud names) and Lesson 237 Wwise init.

Why this matters now (June 2027 dual-branch playtest)
June 2027 teams pass Wwise init rows and invite facilitators on playtest_june while the fest demo depot remains on fest_public. Godot’s default persistence is per executable, not per Steam branch—playtesters save chapter 7, launch the fest build, and see the wrong slot. Lesson 212 fixes label drift; playtest isolation playbook sets depot policy—this lesson files playtest_save_isolation_receipt_v1 on BUILD_RECEIPT.
The Godot save isolation preflight is the ninety-second checklist—238 is the course milestone.
Beginner path (isolation matrix)
| Step | Action | Success check |
|---|---|---|
| 1 | Pin SavePaths autoload + SAVE_SURFACE |
I1 pass |
| 2 | Export per-surface save_slot_label_map |
I2 pass |
| 3 | Save slot 2 on playtest install | Chapter 3 written |
| 4 | Launch fest install—slot 2 empty | I4 pass |
| 5 | Relaunch playtest—slot 2 still chapter 3 | I3 pass |
| 6 | File receipt + BUILD_RECEIPT | isolation_ok: true |
Time: ~64 minutes first dual-depot wiring; ~15 minutes when autoload is pinned.
Developer path (gates I1–I6)
| Gate | Check | Fail when |
|---|---|---|
| I1 | SAVE_SURFACE → unique user:// root |
Shared save folder |
| I2 | save_slot_label_map per surface |
One map for both branches |
| I3 | Playtest round-trip on installed build | Editor-only proof |
| I4 | Fest build no playtest file bleed | Cross-contamination |
| I5 | Steam Cloud basename prefix per surface | fest_ loads playtest remote |
| I6 | Receipt + BUILD_RECEIPT | Promote with shared paths |
I1 — Surface path map (reference)
# scripts/save_surface_paths.gd — autoload SavePaths
const SURFACE_PATHS := {
"playtest_invite": "user://saves_playtest/",
"fest_public": "user://saves_fest/",
}
CI: SAVE_SURFACE=playtest_invite on playtest depot job; fest_public on fest job.
I2 — Per-surface label maps
| Surface | save_root |
Cloud basename example |
|---|---|---|
playtest_invite |
user://saves_playtest/ |
playtest_slot_0.save |
fest_public |
user://saves_fest/ |
fest_slot_0.save |
Extend Lesson 212 maps with save_root—do not duplicate UI labels without path roots.
playtest_save_isolation_receipt_v1.json
{
"schema": "playtest_save_isolation_receipt_v1",
"build_label": "playtest-june-2027-rc1",
"surfaces": {
"playtest_invite": {
"save_root": "user://saves_playtest/",
"save_slot_label_map": "release-evidence/saves/PLAYTEST_SAVE_SLOT_LABEL_MAP.json"
},
"fest_public": {
"save_root": "user://saves_fest/",
"save_slot_label_map": "release-evidence/saves/FEST_SAVE_SLOT_LABEL_MAP.json"
}
},
"isolation_matrix": {
"playtest_slot2_roundtrip": "pass",
"fest_slot2_cross_contamination": "none",
"playtest_relaunch_slot2": "pass"
},
"gates": {
"I1_surface_path_map": "pass",
"I2_label_map_crosswalk": "pass",
"I3_playtest_roundtrip": "pass",
"I4_fest_no_playtest_files": "pass",
"I5_cloud_prefix": "pass",
"I6_build_receipt": "pass"
},
"isolation_ok": true,
"promotion_allowed": true,
"cousin_receipts": {
"save_slot_label": "release-evidence/saves/SAVE_SLOT_LABEL_RECEIPT.json"
}
}
Pin under release-evidence/saves/PLAYTEST_SAVE_ISOLATION_RECEIPT.json.
BUILD_RECEIPT row (I6)
| Column | Pass when |
|---|---|
playtest_save_isolation |
isolation_ok: true |
save_slot_label |
Lesson 212 GREEN (cousin) |
wwise_dsp_init_receipt |
Lesson 237 independent |
ALTER TABLE release_publish_gate ADD COLUMN IF NOT EXISTS
playtest_save_isolation_blocked BOOLEAN NOT NULL DEFAULT false;
Relationship to guide vs Lesson 212
| Artifact | Role |
|---|---|
| Godot save isolation preflight | I1–I6 editor checklist |
| Playtest isolation blog | Depot / scope policy |
| Lesson 212 | Label + Cloud alignment |
| This lesson | BUILD_RECEIPT playtest_save_isolation |
Key takeaways
- Branch isolation needs path roots, not only separate Steam depots.
- Pair 212 (labels) with 238 (paths)—both columns on BUILD_RECEIPT.
- Lesson 237 — audio; 238 — Godot persistence.
- Prove on installed playtest + fest builds—not Editor-only.
- Q3 capstone 244 wires 236–243 including this row.
- Thursday review — one Saves / isolation line.
SAVE_SURFACEmust be set in CI per depot job.- Never copy playtest saves into fest folder “for debug”—invalidates I4.
Common mistakes
- Green 212 but shared
user://—labels OK, paths wrong. - Testing only in Editor—
SAVE_SURFACEunset masks bug. - Same Steam Cloud remote name on both surfaces—I5 fail.
- Skipping fest relaunch after playtest save—I4 never exercised.
- Conflating with Deck static menu—GPU, not saves.
Troubleshooting
| Symptom | Lane |
|---|---|
| Fest loads playtest chapter | I1 + I4 directory audit |
| Cloud overwrites after isolation | I5 + Cloud overwrite help |
| Labels wrong, paths OK | Lesson 212 |
| Works zip, fails Steam | CI SAVE_SURFACE injection |
Mini exercise (60 minutes)
- Ship one build without
SAVE_SURFACE—reproduce fest bleed. - Add autoload + per-surface maps—pass I1–I2.
- Run isolation matrix on two Steam installs.
- File receipt; BUILD_RECEIPT GREEN.
- Link playtest isolation blog in facilitator SOW.
Continuity — Q3 2027 summer playtest wave (236–244)
| Lesson | Receipt focus |
|---|---|
| 236–237 | Art hash + Wwise init |
| 238 (this) | Godot save isolation |
| 239 | Feedback tags → capstone |
Previous: Lesson 237 — Wwise DSP init boot path.
Next: Lesson 239 — Steam playtest feedback tag taxonomy.
FAQ
Same as Godot save isolation guide?
Guide = checklist; 238 = BUILD_RECEIPT column.
Same as Lesson 212?
212 = labels/Cloud; 238 = per-branch save roots + isolation matrix.
Unity project?
Apply same surface → path pattern; receipt schema is engine-agnostic on BUILD_RECEIPT.
Need both 212 and 238 GREEN?
Yes when multi-slot saves ship on multiple Steam surfaces.
Dual-branch playtests fail when fest saves absorb playtest progress—isolate paths, prove the matrix on Steam installs, then promote on BUILD_RECEIPT.