2026 H2 Steam Playtest Invite Isolation vs Public Fest Demo Scope - Trend Playbook
Your producer sends Playtest invites to fifty Discord volunteers. The same week, marketing promotes the October Next Fest demo branch. A streamer installs from the store page, launches what they think is the fest slice, and hits debug UI, chapter six content, and a build_label that still says playtest-wip-05.
Players call it false advertising. Partners call it scope creep. You call it “we thought Playtest was separate.”
Q3 2026 micro-studios run three Steam surfaces at once: friends-and-family beta branches, Steam Playtest invite programs, and public fest demo depots. Each surface has different password rules, store visibility, and save expectations. When scopes bleed together, you get store-demo mismatch recovery threads—not because metadata lied, but because the wrong binary reached the wrong audience.
This Trend-Jacking / News Commentary playbook is comparative infrastructure—not another metadata checklist. It pairs with playtest branch tutorial, Wednesday demo smoke, and save-slot case study.
Non-repetition note: The site already teaches how to create a playtest branch and how to smoke-test fest demos. This URL owns scope isolation between surfaces—three lanes, one map file, promotion gates.
Why this matters now (Q3 2026)
- October Next Fest traffic — Public demo depots get installs from strangers who never read your Discord rules.
- Playtest program growth — More teams enable Steam Playtest invites while also shipping fest SKUs on the same app ID.
- Branch promotion habits — Merging
playtestintofest_publicwithout a scope diff recreates slot-label bugs. - Reviewer and streamer risk — Press keys and Playtest invites are not interchangeable; conflating them pollutes outlet vocabulary.
- Evidence culture — BUILD_RECEIPT rows need a
surfacecolumn, not onlybuild_label.
Direct answer: Maintain playtest_scope_map_v1.json listing every surface, branch, depot, password policy, and demo scope; file playtest_isolation_receipt_v1.json before any promotion that changes public fest visibility.
The failure mode in one paragraph
Naive pattern: One default beta branch, one demo depot, Playtest invites pointed at “whatever is latest,” fest page live when the team feels ready. Playtesters receive keys to builds with full-game menus; fest players receive builds with playtest-only saves copied from internal QA. Store copy describes three chapters; playtest build includes six. Nobody updated build_label after the merge.
What breaks: Not Steamworks mechanics—scope governance. Isolation is a producer document, not a checkbox in the client.
Honest limit: This playbook does not replace Steamworks documentation—it gives micro-studios a decision table before October traffic.
Three surfaces beginners must separate
| Surface | Who installs | Typical password | Store page visible? |
|---|---|---|---|
| Beta branch (FFA) | Invited friends | Branch password | Often hidden / unlisted |
| Steam Playtest | Opt-in playtesters | Invite + app rules | Playtest hub listing |
| Public fest demo | Anyone from fest/store | None (public depot) | Yes during event |
Beginner mistake: Treating “we sent Playtest invites” as “we are ready for Next Fest public demo.” They are different contracts with players.
Working dev mistake: Reusing the same build_id on playtest and fest branches to “save upload time”—upload twice or accept scope lock until next build.
Who should read this
- Producers running Playtest and Next Fest on the same app in H2 2026
- Engineers promoting branches without a scope map
- Teams that finished playtest branch evening pipeline but lack fest isolation
- Leads answering partner diligence “how do you separate QA from public demo?”
Time to read: ~40 minutes. Minimal implementation tonight: draft scope map + one isolation receipt (~90 minutes).
Trend signal vs evergreen advice
| Evergreen truth | 2026 H2 trend twist |
|---|---|
| Use separate branches | Name branches by surface, not mood (fest_public_2026_10) |
| Password playtests | Document invite cap and expiry beside branch password |
| Demo scope discipline | Tie scope to ruleset_id in saves per Construct semver |
| BUILD_RECEIPT logging | Add surface + scope_hash columns |
Beginner path (90-minute isolation pass)
- List every way a player can install your game on Steam this month.
- Copy
playtest_scope_map_v1.jsontemplate below intorelease-evidence/playtest/. - For each row, write demo scope in plain English (chapters, features, endings).
- Verify
build_labelon title screen matches the row players used. - Run Wednesday smoke only on the fest-public row.
- File
playtest_isolation_receipt_v1.jsonwithisolation_pass: trueor block promotion.
Success check: You can answer “which build should a streamer install from the store page?” in one sentence without checking Discord.
Developer path (promotion gates + receipts)
- CI or script rejects promotion if
fest_publicbranchbuild_idequalsplaytestbranchbuild_idunlessscope_hashmatches. - Attach scope map SHA256 to BUILD_RECEIPT.
- Pair promotion with metadata diff.
- Separate
save_slot_label_mapper surface per save-slot case study. - Index playtest feedback with
surfacefield using 18 playtest tools.
playtest_scope_map_v1.json (canonical artifact)
Store at release-evidence/playtest/playtest_scope_map_v1.json:
{
"schema": "playtest_scope_map_v1",
"app_id": "000000",
"updated": "2026-05-24",
"surfaces": [
{
"surface_id": "beta_ffa",
"branch": "playtest-ffa-2026-05",
"depot": "win64_demo",
"password": "branch_password_rotated_monthly",
"store_visible": false,
"demo_scope": "full_vertical_slice_internal",
"build_label": "playtest-ffa-2026-05-24-rc1",
"ruleset_id": "internal_all_chapters",
"cloud_saves": false,
"dev_console_allowed": true
},
{
"surface_id": "steam_playtest_invite",
"branch": "playtest-invite-2026-q3",
"depot": "win64_demo",
"password": "invite_only",
"store_visible": "playtest_hub",
"demo_scope": "chapters_1_3_balance_pass",
"build_label": "playtest-invite-2026-05-24-rc2",
"ruleset_id": "playtest_q3_2026",
"cloud_saves": false,
"dev_console_allowed": false
},
{
"surface_id": "fest_public",
"branch": "fest_public_2026_10",
"depot": "win64_demo",
"password": "none",
"store_visible": true,
"demo_scope": "fest_demo_hour_one_only",
"build_label": "fest-demo-2026-10-rc1",
"ruleset_id": "fest_demo_2026_10",
"cloud_saves": false,
"dev_console_allowed": false
}
],
"forbidden_cross_promotions": [
"playtest-invite build on fest_public branch",
"fest_public build on playtest-invite without scope review"
]
}
Pass: No two surfaces share a build_label unless demo_scope and ruleset_id are intentionally identical (rare).
Decision tree — which surface gets this upload?
Is this build for strangers during a fest/store demo event?
├─ YES → fest_public row only; run I1–I6; file isolation receipt
└─ NO → Is it Steam Playtest opt-in?
├─ YES → playtest-invite row; no store fest visibility
└─ NO → beta_ffa or internal row; dev tools allowed per map
Pin this tree above your Steamworks upload checklist.
Fest week calendar (producer view)
| Phase | fest_public | playtest-invite | beta_ffa |
|---|---|---|---|
| T-14 days | Scope freeze in map | Balance OK | Experiments OK |
| T-7 days | I6 smoke required | Invite email dry-run | Password rotate |
| T-0 fest open | No branch merges without receipt | Pause invites if build unstable | Freeze or detach |
| T+7 days | Patch only with semver rules | Resume invites | Optional |
Rule: During fest open week, treat fest_public row as immutable unless isolation receipt is re-signed.
BUILD_RECEIPT column extension
Add columns to your spreadsheet or JSON log:
| Column | Example |
|---|---|
surface |
fest_public |
branch |
fest_public_2026_10 |
build_label |
fest-demo-2026-10-rc1 |
scope_hash |
sha256 of scope map |
isolation_receipt |
path or pass/fail |
ruleset_id |
fest_demo_2026_10 |
Thursday BUILD_RECEIPT review ritual (when published) should diff surface column—not only byte size.
I-gate deep dives
I1 — build_label separation
Screenshot title screen for each surface on the same day. Filenames:
evidence/playtest/2026-05-24_fest_title.png
evidence/playtest/2026-05-24_invite_title.png
If labels match, players and support cannot distinguish surfaces.
I2 — title scope string
Add optional pause-menu line: Scope: Fest demo — Floor 1 only vs Scope: Playtest — Chapters 1–3.
Playtesters report bugs faster; streamers clip the right expectations.
I3 — dev menus excluded
Grep project for debug, cheat, dev_console, F12 handlers. Fest build must fail grep or use FEST_DEMO define strip. Cross-read dev console opinion.
I4 — FAQ aligned
Extract every save/progress/feature claim from store FAQ. Each claim must appear in demo_scope for fest_public row only. Playtest-only features belong in Playtest hub text, not fest FAQ.
I5 — invite template aligned
Mail merge fields: {{build_label}}, {{demo_scope}}, {{feedback_form_url}}. Send test to yourself before batch. Wrong label in email causes 100% wrong installs.
I6 — fest smoke on installed client
Run full Wednesday smoke S1–S8 on fest_public install only. Playtest smoke is optional but recommended on invite row separately.
Workshop script (45 minutes, whole team)
| Minute | Activity |
|---|---|
| 0–10 | Read three-surface table aloud |
| 10–20 | Fill scope map rows on projector |
| 20–30 | Walk decision tree with last upload |
| 30–40 | Assign I-gate owners |
| 40–45 | Schedule I6 before next fest visibility toggle |
Outputs: signed map version, one isolation receipt draft.
Playtest feedback routing
When 18 playtest tools ingest bugs:
| Field | Required |
|---|---|
surface |
beta_ffa / playtest_invite / fest_public |
build_label |
From title screen |
ruleset_id |
From save or pause UI |
Triage rule: fest_public P0 during fest week; playtest balance P1; beta_ffa P2 unless crash.
Whisper and VOD triage (forward link)
Local Whisper pipeline (backlog) should tag transcripts with surface—do not mix playtest VOD bugs into fest public fix lists without scope review.
Dual-SKU and itch crosswalk
Dual-SKU economics adds non-Steam surfaces. Extend map:
{
"surface_id": "itch_html5",
"demo_scope": "browser_slice_parity_with_fest",
"build_label": "itch-0.6.1-fest-parity"
}
Parity does not mean same binary—means same player promise.
Isolation gates (I1–I6)
| Gate | Question | Fail action |
|---|---|---|
| I1 | Does fest-public build_label differ from playtest? |
Block promotion |
| I2 | Does title screen scope string match map row? | Block promotion |
| I3 | Are dev-only menus excluded from fest build? | Block promotion |
| I4 | Does FAQ describe fest scope only? | Fix store copy |
| I5 | Playtest invite email cite correct build_label? |
Resend template |
| I6 | Installed Steam smoke on fest row only? | Run Wednesday S1–S8 |
Log playtest_isolation_gate.log with pass/fail per gate.
playtest_isolation_receipt_v1.json
{
"schema": "playtest_isolation_receipt_v1",
"map_path": "release-evidence/playtest/playtest_scope_map_v1.json",
"map_sha256": "sha256:example…",
"fest_public_build_label": "fest-demo-2026-10-rc1",
"gates": {
"I1_build_label_separation": true,
"I2_title_scope_match": true,
"I3_dev_menus_excluded": true,
"I4_faq_aligned": true,
"I5_invite_template_aligned": true,
"I6_fest_smoke_pass": true
},
"isolation_pass": true,
"fest_promotion_allowed": true,
"signed_at": "2026-05-24T20:00:00Z"
}
Attach SHA256 to BUILD_RECEIPT row for the fest upload.
Comparative matrix — invite vs branch vs fest
| Dimension | Beta branch FFA | Steam Playtest invite | Public fest demo |
|---|---|---|---|
| Audience | Friends | Opt-in testers | Strangers + fest traffic |
| Expectation | WIP tolerated | Structured feedback | Polish + honesty |
| Menu dev tools | Often allowed | Discouraged | Forbidden |
| Save policy | May reset weekly | Documented | Stable for event week |
| Marketing | None | Light | Heavy |
| Receipt | Optional | Recommended | Required |
Use this table in producer standups—not as engine-specific code.
Promotion workflow (producer)
1. Upload build → assign build_id
2. Update scope map row for target surface only
3. Point ONE branch to build_id
4. Run I1–I6 on fest_public row if touching public visibility
5. File isolation receipt
6. Merge BUILD_RECEIPT + metadata diff same day
7. Send playtest email ONLY after map row matches template
Never “set fest branch to latest” without opening the map file.
Email and Discord templates (isolation-aware)
Playtest invite (correct):
You are on Playtest build
playtest-invite-2026-05-24-rc2— chapters 1–3 only. This is not the October fest demo. Feedback form: [link].build_labelon title screen must match.
Fest announcement (correct):
Public fest demo
fest-demo-2026-10-rc1is live on the store demo depot. Scope: hour-one tutorial + floor 1. Playtest builds are not updated automatically.
Mixing those paragraphs in one message is how streamers install the wrong binary.
Review keys and press (scope lane)
Review keys labeling is a fourth surface for some studios. Add a row:
| surface_id | press_review_2026_10 |
| demo_scope | Same as fest_public OR explicitly extended |
| build_label | Must match email |
Press must never receive playtest-ffa builds without written scope extension.
Save and ruleset isolation
Each surface should carry its own ruleset_id in saves:
| Surface | ruleset_id purpose |
|---|---|
| playtest | Balance experiments allowed |
| fest_public | Frozen for event week |
Loading a playtest save in fest build should fail closed with readable message—see Ren'Py freeze migration pattern.
Cross-read GDevelop save-path freeze for storage paths per surface.
Depot and branch naming conventions (2026 H2)
| Bad name | Better name |
|---|---|
default |
playtest-ffa-2026-05 |
beta |
playtest-invite-2026-q3 |
demo |
fest_public_2026_10 |
Names encode surface, not team mood.
Engine notes (scope implementation)
| Engine | Isolation lever |
|---|---|
| Unity | Scripting define FEST_DEMO strips dev menus |
| Godot | Export template feature tags |
| Construct | NW.js export vs browser SKU split |
| Ren'Py | build.classification per freeze week |
| GameMaker | Separate options for playtest vs fest |
Implementation varies; map file is engine-agnostic.
Snippet-friendly answers
What is the difference between Steam Playtest and a fest demo?
Playtest is an invite/opt-in surface for feedback; fest demo is a public depot with store visibility and stricter scope honesty.
Can I use one build for both?
Only if demo_scope and ruleset_id are identical and I1–I6 pass—usually you should not.
Do Playtest invites need passwords?
Follow Steam Playtest rules plus your branch policy; document both in the scope map.
Common mistakes (seven)
- Promoting latest to fest without map update.
- Same build_label on playtest and fest rows.
- Fest FAQ describing playtest-only features.
- Dev console in fest build (opinion).
- Playtest saves migrating to fest without ruleset gate.
- Skipping I6 smoke on installed fest client.
- No receipt before store page goes live.
Pro tips (six)
- Color-code map rows in producer spreadsheet (green fest, yellow playtest, red internal).
- Screenshot title
build_labelper surface in evidence folder. - Rotate playtest passwords monthly; fest has none.
- Pair with fest marketing cap before paid traffic.
- Require
surfaceon playtest forms. - Archive superseded map versions by date in filename.
Month-one adoption ladder
| Week | Goal |
|---|---|
| 1 | Draft scope map with three rows minimum |
| 2 | First isolation receipt before fest visibility change |
| 3 | BUILD_RECEIPT surface column habit |
| 4 | Review map after any branch merge |
Cross-links (playtest cluster)
| Post | Role |
|---|---|
| Playtest branch tutorial | Create branch |
| 18 playtest tools | Feedback intake |
| Wednesday smoke | Fest binary proof |
| Save-slot case study | Post-merge saves |
| This playbook | Surface isolation |
Q3 diligence and partners
Attach scope map + isolation receipt to Q3 diligence packets—answers “how do strangers avoid WIP builds?” without invented metrics.
Refund and mismatch crosswalk
When wrong surface ships, players file store-demo mismatch reports. Fix map and branch first; metadata second.
Operating review Block 2 prompt
Add to four-Friday operating review:
- Surfaces active this month
- Isolation receipt pass rate
- Any fest promotion without I6
Proof table (example after I6)
| Surface | build_label | I1 | I2 | I3 | I4 | I5 | I6 |
|---|---|---|---|---|---|---|---|
| fest_public | fest-demo-2026-10-rc1 | pass | pass | pass | pass | n/a | pass |
| playtest_invite | playtest-invite-2026-05-24-rc2 | pass | pass | pass | pass | pass | n/a |
| beta_ffa | playtest-ffa-2026-05-24-rc1 | pass | n/a | fail allowed | n/a | n/a | n/a |
Fest row must be all pass before fest_promotion_allowed: true.
Anti-patterns in Q3 2026 threads
| Thread title pattern | Usually means |
|---|---|
| “Demo has debug menu” | fest row pointed at playtest build |
| “Playtesters saw ending” | invite scope too wide |
| “Lost save after fest patch” | ruleset_id bleed |
| “Streamer wrong version” | email/build_label mismatch |
Validate-packet hook (optional)
Extend validate-packet to assert playtest_scope_map_v1.json exists when uploading to fest_public branch.
When this playbook does not apply
- Single-surface apps with no Playtest and no fest demo
- itch-only teams without Steam branches
- Games with no public demo depot planned for 2026
Key takeaways
- Three surfaces—beta FFA, Playtest invite, public fest demo—need separate map rows.
playtest_scope_map_v1.jsonis the producer source of truth.playtest_isolation_receipt_v1.jsongates fest promotion.- I1–I6 gates block label and scope bleed.
- build_label and ruleset_id must align per surface.
- Playtest invites are not fest-ready by default.
- Pair with BUILD_RECEIPT, metadata diff, and Wednesday smoke.
- Review keys are a optional fourth surface row.
- Email templates must cite correct
build_label. - Q3 2026 isolation discipline prevents October mismatch fires.
- Engine implementation varies; map file does not.
- Saves should fail closed across ruleset boundaries.
- Scope map SHA256 belongs on BUILD_RECEIPT fest rows.
- Producers can run beginner 90-minute pass without engineering.
- This is comparative governance—not a fifteenth metadata checklist.
- Re-sign isolation receipt after any branch merge touching fest_public.
- Outbound reference: Steamworks Playtest documentation for invite rules on your partner build.
FAQ
We only use Discord zips—skip?
Run map with one discord_zip row; add Steam rows when you ship branches.
Can playtesters stream?
Only if scope row allows; fest row usually stricter. Add streaming_allowed: true/false to each map row for producer clarity.
Does this replace depot discipline guide?
No—complements depot and branch depth.
One app ID or two?
One app ID is fine with branch isolation—two apps are optional complexity.
What if Playtest and fest share one depot ID?
Depots can be shared; branches and build_labels must still separate scopes—never point both branches at different scopes without updating the map.
Conclusion
October fest traffic does not forgive “we thought Playtest was separate.”
Map the surfaces. Gate the promotion. File the receipt. Then point strangers at the fest row only.
Studios that treat Playtest as “early fest” usually fix isolation in one afternoon—cheaper than a week of public mismatch recovery and refund-language spikes.
Next reads: Playtest branch evening pipeline, Wednesday demo smoke, BUILD_RECEIPT pipeline.