Steam update compatibility #
An ownership receipt is not permission to run arbitrary replacement game code.
verify checks owned bytes and rejects unknown executable hashes, even when
someone has copied that unknown hash into a legacy receipt. The only legacy
exception is the explicitly recorded previous qualified executable. New targets
need an exact reviewed profile in native/compatibility.json.
Checked reconciliation #
w3dev reconcile-game-update
python3 native/build.py
w3dev reconcile-game-update
w3dev reconcile-game-update --apply
w3dev verify
The default operation is a read-only plan under the existing installation lock.
It requires a closed game, no active owner/startup and no uncertain native
delivery. Missing or mismatched candidate adapters reject with build instructions.
--apply performs the same checks again before changing anything:
- Exact executable SHA-256, size, PE64/AMD64 shape and timestamp.
- Matching installed Steam build/target, with no incomplete update.
- The complete stock
.wsscript-tree digest, not just the executable. - Required XInput, Winsock ordinal-2
bind, and USER32 import hooks. - WNB registration signature count, unanimous relative-call targets, registrar
hook prologue, unique
LogChannel, old-helper absence, unique updated string helper, and reviewed code/data target RVAs. - Existing bridge/HUD/native ownership hashes, known previous executable receipt, supported ASI loader, and exact approved replacement adapter bytes.
Only the two devkit-owned adapters and their native receipt may change. The
executable, stock scripts, HUD assets, saves, unrelated mods and settings are
not rewritten. Ordinary install-native no longer adopts an executable hash;
on a reconciled exact profile it verifies an already-current adapter set rather
than recopying changing build outputs.
The checks are intentionally restrictive. A different build, changed stock
scripts, changed loader or different native outputs need a separately reviewed
profile and qualification. There is no --force, arbitrary expected-hash flag
or version-string-only acceptance.
What changed in Steam build 26238013 #
The executable still has 279 matching native-registration sites with complete
target consensus and the expected registrar prologue. Its LogChannel string
initialization no longer contains the nine-byte store that zeroed a fifth stack
argument before the allocator call. The old WNB string pattern therefore matches
zero sites; changing only the executable receipt would leave that resolver
incompatible.
The pinned WNB build applies a small source patch in a private build copy. It preserves the old pattern and tries the new one only when the old pattern has zero matches; ambiguous matches still reject. The allocator/empty-string/copy offsets move by nine bytes. Disassembly supplies the same four register arguments as WNB's existing allocator typedef. Other resolver logic and callback ABI are unchanged. See native build provenance.
Static matching does not prove all ABI semantics. verify and the plan report
qualification.live_qualified separately; it remains false until the matching
reviewed report exists and records a passing executable/native chain. A maintainer
may apply the statically reviewed candidate for bounded qualification, but must
not publish or describe it as consumer-ready before that qualification succeeds.
The explicit harness is:
python3 -m tests.live.game_update_acceptance
It uses the normal owner and a hash-verified fixture, exercises strings, names, native input dispatch, movement, control boundaries and the installed HUD, then closes unsaved and audits restoration. It does not qualify OBS/audio capture, consumer policy, every native API, every game state or physical input latency.
The reviewed qualification records 384 offline tests in both worktree and source-only environments and 16 passing live checks. It also retains the failed first startup: Steam shader processing outlasted the debugger budget and launched the game later. No successful compilation was inferred from that timeout; the delayed owned process was identified and closed, and a fresh restoration audit preceded the passing retry.
Interrupted updates and rollback #
Apply retains old receipt/adapter bytes with checked hashes and fsyncs them before replacement. Each same-directory staging file has a transaction-unique name and a durably recorded inode identity before its contents are written. Completed writes and directory replacements are flushed. The native receipt is published last. A crash may leave a partial multi-file transaction; verification then blocks ordinary launch rather than treating mixed bytes as ready.
Inspect the returned artifact, then use:
w3dev reconcile-game-update --rollback ARTIFACT
Rollback requires closed-game exclusion and validates the retained receipt, backup hashes and actual target hashes. It refuses unrelated external changes. Partial owned staging files are retained as evidence before removal; unknown identities are not deleted. A rollback failure preserves the original error and cleanup failure together.
Rollback restores adapters and their previous receipt, never the Steam executable. Consequently it can intentionally return the installation to a blocked state until compatible tooling is available. It never restores saves or overwrites independently changed settings. If Steam updates again during a transaction, stop and inspect the retained evidence rather than retrying blindly.