# 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 ```sh 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 `.ws` script-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](../native/README.md). 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: ```sh 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](validation/steam-update-26238013.json) 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: ```sh 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.