Stop Running setlive on Default Branch Without a Numbered SETLIVE Exception List - 2026 Opinion

Thursday 6:40 p.m., October upload week: weekly depot jq is GREEN. Depot upload evening shows steampipe_upload_ok: true. Someone opens Steamworks, sees an RC label that "looks fine," and runs setlive against default because "players will find it faster" and "we'll move the fest branch later." Twenty minutes later a tester installs from the wrong branch. Wrong default branch recovery becomes tonight's ambulance instead of tomorrow's prevention.
October 2026 upload week is when compassionate default promotions destroy the RC evidence trail you built after localization capstone. HOTFIX exception opinion disciplined live-week binary bumps. MERGE exception opinion disciplined post-fest trunk merges. Upload week needs a cousin list with different stakes: every setlive that targets default (or any non-RC label) during the upload window must appear as the next integer in setlive_exception_list_receipt_v1.json—not Steamworks vibes, not "RC looked fine," not Slack "just this once."
This Opinion & Hot Takes piece makes a narrow claim: during October Next Fest upload week, no setlive to default (and no silent branch-pointer flip) happens unless the change is SETLIVE-00N with dry-run proof, producer sign-off, and BUILD_RECEIPT latch—refuse promotions that skip the next number even when SteamPipe queues are calm.
Non-repetition note: HOTFIX owns live-week H1–H6 binary promotions. SHIP owns holiday O1–O6. MERGE owns post-fest trunk M1–M6. Wrong default branch case study #4 owns B1–B6 recovery after the damage. 12 setlive preflight checks owns checklist theater before promote. This URL owns numbered SETLIVE exception list + S1–S6 when upload-week default-branch temptation peaks.
Pair wrong default branch #4, HOTFIX cousin, overtime worksheet #8, 12 setlive checks, SteamCMD validation tools, depot branch mismatch help, and GameMaker setlive dry-run lesson. Forward #10 Wednesday depot smoke and #12 Friday upload capstone.
Why this matters now (October 2026 upload week)
- RC labels look fine while pointers lie — Steamworks UI comfort is not branch-pointer truth (case study #4).
- Default feels faster — Producers shortcut to
defaultunder store-publish pressure from metadata freeze. - Weekly depot jq cannot save a wrong branch — Depot weekly #7 proves hash identity; it does not authorize
defaultsetlive. - Overtime hours chase the wrong fix — Overtime worksheet #8 O-SETLIVE routes here when target ≠ RC.
- Partners audit branch intent — Diligence zips now ask for setlive target and exception ID, not "we promoted successfully."
Direct answer: Maintain setlive-exception-list-2026-upload.md with monotonic SETLIVE-001…N, file setlive_exception_list_receipt_v1.json, set BUILD_RECEIPT setlive_exception_list_ok: true, run dry-run + 12 preflight checks same calendar day any exception targets default—refuse setlive that skips the next number.
The opinion in one paragraph
Upload week is not a Steamworks click-through. If you promote to default during the October upload window without incrementing a numbered SETLIVE exception, you did not help discovery—you created a second live surface inside the RC pipeline: players install bits your receipts describe as fest_rc, partners see GREEN flags that hide pointer slip, and recovery nights burn overtime caps that should have paid for smoke. Micro-studios cannot afford two branch truths in one week. Numbered SETLIVE lists are the minimum authorization layer between dry-run logs, weekly depot honesty, and the recovery case study you hope never to need. Verbal "RC looked fine" is how teams ship the wrong branch with a green Steamworks toast.
Who this opinion is for
| Audience | Why read |
|---|---|
Solo founder in #october-upload |
Copy-paste "next SETLIVE number or no default promote" |
| Producer before setlive | Block promote until list matches dry-run + RC label |
| Engineer | Wire verify_setlive_exception_list.sh before CI setlive |
| QA lead | Refuse install smoke on unexplained default builds |
HOTFIX vs SETLIVE — format ladder
| List | Window | Schema | Primary gate |
|---|---|---|---|
| HOTFIX exception | Feb live D1–D7 | hotfix_exception_list_receipt_v1 |
H1–H6 |
| SHIP exception | Dec freeze → Jan | ship_exception_list_receipt_v1 |
O1–O6 |
| MERGE exception | Mar post-fest | merge_exception_list_receipt_v1 |
M1–M6 |
| SETLIVE exception | Oct upload window | setlive_exception_list_receipt_v1 |
S1–S6 |
| Wrong default recovery #4 | After mismatch | default_branch_recovery_receipt_v1 |
B1–B6 |
Rule: HOTFIX rows do not substitute for SETLIVE rows during upload week—HOTFIX is live-fest binary content; SETLIVE is branch pointer authorization. Prefer zero SETLIVE exceptions: keep setlive on fest RC. When default is unavoidable, start at SETLIVE-001 and archive the list at Friday upload capstone (#12).
Beginner path — when default is OK vs never OK
Never OK (upload week default)
- "RC label looked fine in Steamworks screenshots."
- "Default is what press keys already use."
- "We'll move fest branch after store publish."
- "QA is busy; default is easier to find."
- "setlive exit code was 0."
OK only with SETLIVE-00N
- Live-breaking crash on fest RC with documented rollback to last known RC hash.
- Partner-mandated default promote with written partner ticket ID.
- Intentional soft-launch surface where store page and BUILD_RECEIPT both claim
defaultand fest RC is retired in the same receipt. - Emergency rollback from a broken fest RC pointer with same-day installed-client smoke (case study B1/B5).
Prefer instead of default
- Promote fest RC label with 12 preflight checks.
- Update weekly depot jq
branch_intent/rc_label. - Give QA a named beta branch URL or Steam branch password—not silent default.
- If overtime is the real pressure, use O-SETLIVE—do not "save hours" by skipping the list.
Numbered list in 25 minutes
Copy into release-evidence/steam/setlive-exception-list-2026-upload.md:
# Numbered SETLIVE exception list (October 2026 upload week)
upload_window: 2026-W41
list_owner: producer
next_seq: 1
default_policy: forbid_without_exception
| Seq | Date | Summary | Target branch | Intended RC label | Dry-run path | Installed smoke? | Owner | Partner ticket |
|-----|------|---------|---------------|-------------------|--------------|------------------|-------|----------------|
| SETLIVE-001 | (reserved) | — | — | — | — | — | — | — |
Beginner rules:
- Next
setlivetodefaultmust benext_seq—no SETLIVE-003 before SETLIVE-002 exists. - Dry-run log required same day—pair GameMaker dry-run lesson or steamcmd dry-run archive.
- Installed-client smoke required—Steamworks green is not player truth (help: build label mismatch).
- Feature polish ⇒ DEFER—SETLIVE list is branch authorization, not a place to hide content hotfixes (use HOTFIX cousin during live week).
Success check: A producer can answer "which SETLIVE number authorized default?" without asking engineering to open Steamworks.
Developer path — gates S1–S6
| Gate | Check | Fail action |
|---|---|---|
| S1 | exceptions[] seq integers 1..N contiguous |
Fix gaps before setlive |
| S2 | next_seq == N+1 in markdown matches JSON |
Sync list + receipt |
| S3 | Target default (or non-RC) ⇒ dry_run_log_path + installed_smoke_path same calendar day |
Block setlive |
| S4 | intended_rc_label documented; BUILD_RECEIPT setlive_target_label matches exception or RC |
Fix label lineage |
| S5 | Exception dated inside upload window (october_upload_window_allowed) |
Reject out-of-window rows |
| S6 | setlive_exception_list_ok: true + producer sign-off path |
Fail jq bundle |
setlive_exception_list_receipt_v1.json (template)
{
"schema": "setlive_exception_list_receipt_v1",
"upload_window": "2026-W41",
"generated_at": "2026-10-09T18:00:00Z",
"next_seq": 2,
"default_policy": "forbid_without_exception",
"exceptions": [
{
"seq": 1,
"id": "SETLIVE-001",
"date": "2026-10-09",
"summary": "Partner-mandated default promote for soft review keys",
"target_branch": "default",
"intended_rc_label": "october_next_fest_2026_rc",
"reason_code": "PARTNER_TICKET",
"partner_ticket_id": "PARTNER-4481",
"dry_run_log_path": "release-evidence/steam/dry-run/SETLIVE_001_DRYRUN.log",
"installed_smoke_path": "release-evidence/steam/smoke/SETLIVE_001_INSTALLED.json",
"producer_signoff_path": "release-evidence/steam/SETLIVE_001_SIGNOFF.json",
"weekly_depot_receipt_path": "release-evidence/steam/weekly/2026-W41.json",
"owner": "producer",
"rollback_build_id": "october-fest-rc-20261006-143022"
}
],
"pointers": {
"october_upload_window": "release-evidence/localization/2026-09-26/localization_freeze_capstone_receipt_v1.json",
"twelve_check_receipt": "release-evidence/steam/depot_owner_receipt_v1.json"
},
"gates": {
"S1": "GREEN",
"S2": "GREEN",
"S3": "GREEN",
"S4": "GREEN",
"S5": "GREEN",
"S6": "GREEN"
},
"setlive_exception_list_ok": true
}
Store canonical copy at release-evidence/steam/SETLIVE_EXCEPTION_LIST_RECEIPT.json.
BUILD_RECEIPT rows
{
"october_upload_window_allowed": true,
"setlive_target_label": "default",
"setlive_exception_list_ok": true,
"setlive_exception_count": 1,
"setlive_exception_list_receipt": "release-evidence/steam/SETLIVE_EXCEPTION_LIST_RECEIPT.json",
"setlive_allowed": true
}
Fail-closed: If setlive_target_label is default and setlive_exception_list_ok is false or count is 0, CI must refuse setlive. If target remains fest RC, exception list may be empty with setlive_exception_list_ok: true and next_seq: 1 (no exceptions filed)—document default_policy: forbid_without_exception.
Empty-list GREEN (preferred)
{
"schema": "setlive_exception_list_receipt_v1",
"upload_window": "2026-W41",
"next_seq": 1,
"default_policy": "forbid_without_exception",
"exceptions": [],
"gates": {
"S1": "GREEN",
"S2": "GREEN",
"S3": "GREEN",
"S4": "GREEN",
"S5": "GREEN",
"S6": "GREEN"
},
"setlive_exception_list_ok": true,
"notes": "No default setlive; all promotes target october_next_fest_2026_rc"
}
Empty is honest. Fake SETLIVE-001 "placeholder" rows are theater.
verify_setlive_exception_list.sh
#!/usr/bin/env bash
set -euo pipefail
LIST="${1:-release-evidence/steam/SETLIVE_EXCEPTION_LIST_RECEIPT.json}"
BR="${2:-BUILD_RECEIPT.json}"
jq -e '.schema == "setlive_exception_list_receipt_v1"' "$LIST" || exit 1
COUNT=$(jq '.exceptions | length' "$LIST")
for i in $(seq 1 "$COUNT"); do
ACT=$(jq -r --argjson n "$i" '.exceptions[] | select(.seq == $n) | .seq' "$LIST")
[[ "$ACT" == "$i" ]] || { echo "S1 fail: missing seq $i"; exit 2; }
done
TARGET=$(jq -r '.setlive_target_label // empty' "$BR")
if [ "$TARGET" = "default" ]; then
[ "$COUNT" -ge 1 ] || { echo "S3 fail: default target without exception"; exit 3; }
jq -e '
all(.exceptions[];
(.dry_run_log_path | type == "string" and length > 0)
and (.installed_smoke_path | type == "string" and length > 0)
)
' "$LIST" || { echo "S3 fail: missing dry-run or installed smoke"; exit 3; }
fi
jq -e '.setlive_exception_list_ok == true' "$LIST" || exit 6
jq -e --argjson c "$COUNT" '
(.setlive_exception_count // $c) == $c
' "$BR" >/dev/null 2>&1 || true
echo "setlive_exception_list verify: OK"
Exit codes: 1 schema, 2 S1 gaps, 3 S3 default without proof, 6 S6 latch.
Setlive theater vs honest SETLIVE exception
| Theater | Honest |
|---|---|
| "RC looked fine" screenshot | Dry-run log + installed smoke path |
| setlive exit 0 | Branch pointer audited on player client |
| Slack "just default for press" | SETLIVE-00N + partner ticket |
| Empty recovery folklore | Prefer zero exceptions; recovery #4 only after failure |
| Overtime without exception ID | O-SETLIVE requires this list |
Scenario matrix
| Scenario | Approve default setlive? | Why |
|---|---|---|
| RC label visible; no exception | No | Looks-fine is not authorization |
| Partner ticket requires default + SETLIVE-001 | Yes, capped | Document ticket + smoke |
| Weekly depot jq RED | No | Fix identity first (#7) |
| Crash on fest RC; rollback to last RC hash | Prefer RC rollback | Default only if partner/store requires it |
| Press keys already on default | Maybe | File SETLIVE-00N and update store claims same day |
| Overtime request to "just setlive default" | No until list | Route O-SETLIVE → this opinion |
| After mismatch already shipped | Recovery first | Run B1–B6 case study, then start numbered list |
Proof table
| Artifact | Proves | Does not prove |
|---|---|---|
| SETLIVE-00N row | Authorization for non-RC target | Gameplay quality |
| Dry-run log | Command intent before promote | Player install truth |
| Installed smoke | Player-visible branch | Store metadata freeze |
| Empty exception list GREEN | Policy held: no default | Depot hash honesty |
| S6 latch | CI may allow setlive job | Wednesday smoke pass |
| Case study B1–B6 | Recovery after failure | Prevention (this URL) |
Producer stand-up script (60 seconds)
- "Is setlive target fest RC or default?"
- "If default—what SETLIVE number?"
- "Dry-run path and installed smoke path?"
- "Weekly depot jq still GREEN for
branch_intent?" - "Overtime hours mapped to O-SETLIVE?"
- "If any no → no setlive today."
jq one-liners
Latch
jq -e '.schema == "setlive_exception_list_receipt_v1"
and .setlive_exception_list_ok == true' \
release-evidence/steam/SETLIVE_EXCEPTION_LIST_RECEIPT.json
Contiguous sequences
jq -e '
(.exceptions | length) as $n
| ([.exceptions[].seq] | sort) == [range(1; $n+1)]
' release-evidence/steam/SETLIVE_EXCEPTION_LIST_RECEIPT.json
Default target requires exception
jq -e '
if .setlive_target_label == "default" then
(.setlive_exception_count // 0) >= 1
else true end
' BUILD_RECEIPT.json
CI sketch
- name: Verify SETLIVE exception list
run: bash scripts/verify_setlive_exception_list.sh
- name: Block default setlive without exception
run: |
jq -e '
.setlive_target_label != "default"
or (.setlive_exception_list_ok == true and (.setlive_exception_count // 0) >= 1)
' release-evidence/05-operations/BUILD_RECEIPT.json
Place after 12 preflight checks receipt and before the setlive job. Never invert.
Partner diligence zip
setlive_exception_list_receipt_v1.json- BUILD_RECEIPT excerpt with
setlive_target_label+setlive_exception_list_ok - Dry-run logs for each SETLIVE-00N
- Installed smoke JSON
- Link to wrong default recovery if any B-gate ran
- SteamCMD tools checklist evidence
Zip name: {studio}_setlive_exception_{iso_week}_2026.zip.
FAQ
Same as 12 setlive preflight checks?
No. The twelve checks are mechanical preflight. This opinion is authorization policy for when target is default or non-RC.
Same as HOTFIX exception list?
No. HOTFIX numbers binary content during live fest. SETLIVE numbers branch pointer exceptions during upload week.
Same as wrong default branch case study?
No. Case study #4 is recovery after failure (B1–B6). This URL is prevention via numbered authorization (S1–S6).
Can we setlive default with zero exceptions if store is live?
Only if BUILD_RECEIPT and store claims both intend default and fest RC is formally retired in the same receipt—still file SETLIVE-001 documenting retirement, or you will invent folklore later.
Does setlive exit 0 clear S3?
No. Exit code can be 0 on the wrong branch. Installed smoke is mandatory for default exceptions.
Where does overtime fit?
Overtime worksheet #8 O-SETLIVE stops unpaid thrash; this list supplies the exception ID that overtime actuals must reference.
When do we archive the list?
At forward #12 Friday upload capstone—or when upload window closes. Do not keep adding SETLIVE rows into live-week HOTFIX lists.
What if CI uploads only?
Still require exception list for default targets. operator: ci_runner does not replace producer sign-off on S3 paths.
Key takeaways
- Default setlive during upload week without SETLIVE-00N is theater.
- Gates S1–S6 on
setlive_exception_list_receipt_v1.json. - Prefer empty list GREEN—fest RC only.
- Default exceptions need dry-run + installed smoke same day.
- Latch
setlive_exception_list_okseparately fromsteampipe_upload_ok. - Pair case study #4 for recovery, this URL for prevention.
- Pair HOTFIX / MERGE / SHIP cousins—different windows.
- 12 preflight checks are necessary; not sufficient for default authorization.
- Overtime #8 O-SETLIVE routes here.
- Use SteamCMD tools, help mismatch fix, course dry-run.
- Pair Wednesday depot smoke #10 D6 branch honesty; forward #12 capstone.
- Steamworks "looks fine" is not a receipt field.
Related reads
- We Recovered Wrong Steam Default Branch After Localization Capstone GREEN
- Stop Hotfixing Fest Demos During Live Week Without Numbered HOTFIX Exceptions
- 12 Pre-Flight Checks Before steamcmd setlive October Fest 2026
- October Upload Week Engineering Overtime Cap Worksheet
- Wednesday Depot Smoke BUILD_RECEIPT Row Review Before Thursday Store Publish — D6 consumes SETLIVE honesty before
store_publish_allowed - jq Gate Sketch for october_upload Weekly Depot Row Diff
- SteamCMD SteamGuard Depot Owner Validation Tools
- Steam Depot Promoted Playtest Build Label Mismatch Help
- GameMaker Steam setlive Branch Dry-Run Course Lesson
- We Recovered Fest-Day setlive Mismatch After February RC Label
Closing
RC labels that "look fine" are how October upload weeks invent a second live branch. Number the exception, or keep setlive on fest RC.
When someone asks to promote default because Steamworks was green, the answer is SETLIVE-00N with dry-run and installed smoke—or no. Prevention is cheaper than B1–B6 recovery, and honesty is cheaper than another unpaid overtime night chasing the wrong pointer.