Real CONTRABAND development case

Release gates: QA, cloud, then a build

A Martinez AI Studios education product

A Steam App ID on the store is not a substitute for a local gate that can fail.

CONTRABAND’s Steam client (public App ID 4901100) records an explicit release gate: npm run qa:release:logic (unit tests, module cycles, edition + story-graph + validate-release) plus Electron runners for game QA and Last Run (English/Spanish × keyboard/mouse and gamepad). The 15 Aug 2026 log also records save/cloud rules: autosave must not overwrite before load, New Game uploads the new run to Steam Cloud, and a future save schema is refused. This page does not document Steamworks admin identifiers, builder accounts, or upload credentials.

Category
Release engineering
Project
CONTRABAND
Recorded
2026-08-15
Status
Verified · published

1. Symptom

Without a gate, a build could ship with Last Run broken on one language or one control scheme, a story graph that still referenced unreachable chapters, or a cloud save that clobbered a newer local file. Playtesting one machine in one language hid that.

2. Player impact

Wrong-language Last Run, gamepad cells that never saw the tutorial, or a cloud restore that ate progress are player-facing failures. They are not “Steam being down.” They are missing checks before the depot goes live.

3. Reproduction

Read package.json scripts qa:release:logic and qa:release. Run the logic target in CI or locally; it must be allowed to fail. The development log for v0.4.89–v0.4.91 states Last Run Electron EN/ES × KBM/gamepad 4/4 and qa:release green as the pass condition. Do not paste Steam Guard, builder logins, or Partner IDs into public notes.

4. System ownership

Scripts: qa:release:logic and qa:release. Cloud: play/systems/steam-cloud.js (remote file name, debounce, backup before overwrite). Saves: save-schema / state. Last Run harness: last-run-qa-runner.js. Versioning of the marketing/game label is a separate documented pipeline and is not this incident.

5. Incorrect assumption

If it ran on the developer’s PC, it is ready for Steam. Cloud sync is “Steam’s problem.” One Last Run pass in English on mouse covers Spanish and gamepad. Store presence equals release engineering.

6. Root cause

Release is a matrix: language × input × save/cloud × story graph × packaged exe. A single playthrough samples one cell. Autosave-before-load and cloud overwrite are ordering bugs; they only show up with two machines or a New Game after a cloud file exists. Without a named npm script that fails the build, those cells stay optional.

7. Minimal fix

Make qa:release:logic blocking (tests + validate-release + story graph). Add Electron cells for Last Run language × device. Document cloud rules: do not clobber before load; New Game must upload the new run; refuse unknown future schemas. Keep Steamworks admin data out of public case studies.

8. Regression test

qa:release:logic is the automated bundle. last-run-qa-runner.js encodes the 4-cell Last Run matrix. steam-cloud.js is covered by steam-cloud-flush tests in the log. This Academy page does not re-run those binaries.

9. Release validation

Development log 15 Aug 2026, v0.4.89 (persistence/cloud/story graph) and v0.4.91 (qa:release green, Last Run harness). Public Steam page remains store.steampowered.com/app/4901100/. No depot passwords or Partner IDs are published here.

10. Generalized lesson

Shipping is a checklist that can fail, not a screenshot of the store. Encode language, input, and persistence as cells. Never put Steamworks admin identity in educational write-ups. AI that “just uploads the build” skips the only tests that catch Last Run and cloud ordering.

Public evidence

  • package.json scripts qa:release and qa:release:logic (unit + story-graph + validate-release + Electron QA).
  • CONTRABAND development log, 15 Aug 2026, v0.4.89–v0.4.91.
  • play/systems/steam-cloud.js (public behavior only: named save file, debounce, backup).

Related flagship modules

Related notes