Lesson 246: Ren'Py Playtest Save Language Isolation Receipt on BUILD_RECEIPT (2026)

Direct answer: Before July playtest scale on a Ren'Py SKU with fest_public still live, file renpy_playtest_save_language_receipt_v1.json proving config.save_directory and language persistent keys are unique per SAVE_SURFACE, pass the installed-build isolation matrix (playtest slot 2 round-trip, fest slot 2 empty, no language pref bleed), and link cousin po_hash_language_receipt_v1 from Lesson 225—then promote BUILD_RECEIPT renpy_playtest_save_language_ok. Distinct from po_hash_language (PO packaging) and Lesson 238 Godot save isolation (user:// paths).

Lesson hero for Ren'Py playtest save language isolation receipt

Why this matters now (July 2027 Ren'Py dual-branch playtest)

July 2027 visual-novel teams pass Lesson 225 PO-hash on the fest depot, then invite playtest_july while itch and Steam fest builds stay public. Playtesters finish in 日本語, launch the fest exe, and see English menus—or chapter 7 in fest slot 2—because persistent.language and config.save_directory were never isolated per surface.

The Ren'Py save/language isolation preflight is the ninety-second checklist—246 is the BUILD_RECEIPT milestone. Pair Lesson 245 wasm crash row and Lesson 239 tag save_isolation.

Beginner path (dual-exe matrix)

Step Action Success check
1 Confirm Lesson 225 GREEN on fest Cousin PO hash
2 Pin save_surface_config.rpy per surface S1 pass
3 Isolate language persistent keys S2 pass
4 Playtest exe: JP + save slot 2 S3 pass
5 Fest exe: slot 2 empty, language per fest policy S4 pass
6 File receipt + BUILD_RECEIPT save_language_isolation_ok: true

Time: ~62 minutes first dual-export wiring; ~15 minutes when surface config is pinned.

Developer path (gates S1–S6)

Gate Check Fail when
S1 SAVE_SURFACEconfig.save_directory Shared save folder
S2 Language persistent per surface persistent.language shared
S3 Playtest installed round-trip Editor-only proof
S4 Fest: no save bleed + no language bleed Cross-contamination
S5 build_label on receipt Mismatch vs playtest pin
S6 renpy_playtest_save_language_receipt_v1.json save_language_isolation_ok: false

Cousin receipt crosswalk

Cousin Schema When required
Lesson 225 po_hash_language_receipt_v1 Fest SKU PO packaging
Lesson 238 playtest_save_isolation_receipt_v1 Godot SKU same policy
This lesson renpy_playtest_save_language_receipt_v1 Ren'Py save + language surfaces

Do not merge PO hash proof into this JSON—reference paths only.

renpy_playtest_save_language_receipt_v1.json

{
  "schema": "renpy_playtest_save_language_receipt_v1",
  "build_label": "playtest-july-2027-rc1",
  "surfaces": {
    "playtest_invite": {
      "save_directory": "MyVN-playtest-1",
      "language_persistent_key": "playtest_language",
      "boot_language": "japanese"
    },
    "fest_public": {
      "save_directory": "MyVN-fest-1",
      "language_persistent_key": "fest_language",
      "boot_language": "english"
    }
  },
  "isolation_matrix": {
    "playtest_slot2_roundtrip": "pass",
    "fest_slot2_cross_contamination": "none",
    "fest_language_pref_bleed": "none"
  },
  "cousin_receipts": {
    "po_hash_language": "release-evidence/localization/PO_HASH_LANGUAGE_RECEIPT.json",
    "godot_save_isolation": "release-evidence/saves/PLAYTEST_SAVE_ISOLATION_RECEIPT.json"
  },
  "gates": {
    "S1_save_directory": "pass",
    "S2_language_persistent": "pass",
    "S3_playtest_roundtrip": "pass",
    "S4_fest_isolation": "pass",
    "S5_build_label": "pass",
    "S6_receipt": "pass"
  },
  "save_language_isolation_ok": true,
  "promotion_allowed": true
}

Pin under release-evidence/saves/RENPY_PLAYTEST_SAVE_LANGUAGE_RECEIPT.json.

BUILD_RECEIPT row (S6)

Column Pass when
renpy_playtest_save_language_ok save_language_isolation_ok: true
po_hash_language Lesson 225 cousin (separate column)
playtest_save_isolation Lesson 238 cousin if Godot SKU ships

Thursday row reviewRen'Py isolation line: S4 matrix pass Y/N.

Key takeaways

  1. 225 PO hash246 save/language isolation—run both before July scale.
  2. config.save_directory must differ per SAVE_SURFACE (S1).
  3. persistent.playtest_language vs fest_language—never one shared persistent.language (S2).
  4. Prove on two installed exes—not Ren'Py launcher alone (S3–S4).
  5. Godot Lesson 238 shares policy, different engine wiring.
  6. Tag triage via Lesson 239save_isolation, not new emoji.
  7. Q4 capstone 253 will wire 245–252 including this row.
  8. “Weblate 100% but English” → PO-hash guide—not this lesson.
  9. “Fest demo Japanese after playtest” → this lesson S4 language bleed.
  10. SAVE_SURFACE injection belongs in CI per Steam depot job.

Common mistakes

  • GREEN 225 but shared save_directory between exes.
  • S2 skipped—menus flip language without player input.
  • Merging schemas into po_hash_language_receipt_v1.
  • Testing only itch WebGL when receipt targets desktop VN exes—file surface honestly.
  • Conflating with Lesson 212 labels-only cousin.

Troubleshooting

Symptom Lane
Fest loads playtest chapter S1 + S4
Fest language = playtest JP S2 persistent keys
English menus, hashes OK R-gates rpyc
Godot SKU same policy Lesson 238
Wrong depot Lesson 201

Mini exercise (60 minutes)

  1. Ship one build with shared save_directory—reproduce fest bleed.
  2. Add save_surface_config.rpy + S2 keys—pass matrix on two installs.
  3. Link cousin PO_HASH_LANGUAGE_RECEIPT.json.
  4. File receipt; BUILD_RECEIPT GREEN.
  5. Pin facilitator note beside playtest isolation blog.

Continuity — Q4 2027 July playtest scale (245–253)

Lesson Receipt focus
245 Bevy wasm crash label
246 (this) Ren'Py save + language isolation
247 Unreal menu minidump build_label
253 Q4 capstone (queued)

Previous: Lesson 245 — Bevy playtest crash build_label
Next: Lesson 247 — Unreal playtest menu minidump build_label

FAQ

Same as Lesson 225?
225 = PO hash packaging; 246 = save roots + language persistent per surface.

Same as save isolation guide?
Guide = S1–S6 checklist; 246 = BUILD_RECEIPT promotion.

Same as Lesson 238?
238 = Godot user://; 246 = Ren'Py save_directory + persistent.

English-only VN?
Set renpy_playtest_save_language_ok: n/a when only one surface ships—do not fake matrix.


Localized playtest must not rewrite fest saves or menus—isolate directories and language keys, prove the matrix on installed exes, then renpy_playtest_save_language_ok on BUILD_RECEIPT.