Research notes

Build Lock

Current build
2026.08.11.1121610.2-Rel-i343-Meteorite-2607-CU4 (Steam), Unreal Engine 5.5.4
Locked
2026-08-18
Lock file
config/hce-build.lock.json

Raw investigation log, rendered from the repository. Curated summaries live under Documentation.

Current build: 2026.08.11.1121610.2-Rel-i343-Meteorite-2607-CU4 (Steam), Unreal Engine 5.5.4 Locked: 2026-08-18 Lock file: config/hce-build.lock.json

Every finding in docs/ is only true of the build it was measured on, and the game updates without asking. Before CU3 each note restated its own hash, which meant eight places to update and eight chances to miss one. This is the single place that answers "what am I running, and is it what the notes describe".


Headline hashes

ArtifactBytesSHA-256
HaloCampaignEvolved.exe230,866,704EB1DACA659207F2B5C8A6FD922917195AE9C8AE19E771E396E08906282A4B152
HaloSimulation_tag_release.dll14,668,560C8C144404ADF61A9DE821C996682A7E66ABADD7E530397D3BBDE31C123203BF7
PartyWin.dll4,002,840037CAFB5B3682A4EAB8D55A72ED79BBE8D2A73EAC524AD65377217AC67B9F222
PlayFabMultiplayerWin.dll1,845,2808991E3B9ED098FCF4430C790CC3ABEDC9080F7E567E907F258326B52DAF1A756
libHttpClient.Win32.dll258,320E9BD94CFC493EF97E5473D47BFA2DE67C2310CF401F9C7C4C6CD0206742E9E1C

The tag-DLL hash is what selects a live-mode profile: the RVAs of the simulation's tag table and string-id registry in crates/blam-live/src/tagtable.rs belong to this exact binary (tag_table_and_string_ids.md).

The lock file carries all 252 shipped files — every binary, all 31 IoStore container sets (.utoc/.ucas/.pak) and the bundled video, 74 GiB in total.

Not locked, on purpose:

  • Binaries/Win64/ue4ss/ and Content/Paks/LogicMods/ — what we installed, not what shipped.
  • *_P.pak/.ucas/.utoc override containers — installed mods by the pak loader's own naming convention. One (pakchunk990-MJOLNIRWORLD-Windows_P) had leaked into the CU3 lock, which surfaced when the vanilla CU3 depot download matched all 252 shipped files and "missed" exactly the three we had installed ourselves.
  • Binaries/Win64/dwmapi.dll — the UE4SS proxy. It sits next to the executable rather than inside ue4ss/, so it looks shipped and is not. A lock that differs between a modded and a vanilla install cannot answer the question it exists to answer.
  • *.dmp, *.log — local residue.

What CU4 changed

CU4 landed on 2026-08-11. Verifying the CU3 lock against it reported 49 changed files and none added or removed: the host executable, the simulation DLL, 17 of the 31 container sets (global, pakchunk0, and most level chunks), and a third-party sweep (nine boost DLLs, libHttpClient, OpenColorIO, tbb, CrashReportClient).

CU3 was overwritten in place, but its depot manifest was still on Steam's CDN: tools/steam_depot_fetch.py recovered it bit-for-bit (all 252 shipped files matched this lock), both builds are snapshotted, and the CU3 → CU4 tag diff ran for real. See game_update_pipeline.md for the pipeline and what that diff found.


Using it

Regenerate after a game update, or verify an install against the committed lock:

python tools/build_lock.py "<install root>" --generated <date> -o config/hce-build.lock.json
python tools/build_lock.py "<install root>" --verify config/hce-build.lock.json

--verify reports the version mismatch first, then every changed and missing file, and exits nonzero if the install is not the locked build. --binaries-only skips the 74 GiB content pass and takes a few seconds, which is usually all you need to answer "did the executable move".

tools/game_snapshot.py snapshot <root> --lock-out config/hce-build.lock.json hashes the same files once and produces both the snapshot and the lock, so after an update prefer it to running the full pass twice.

Paths are recorded relative to the install root, so two machines on the same build produce identical locks.


What has been re-verified on CU4

Verified on the CU4 binaries above (2026-08-18):

ClaimWhere
All four UE4SS AOB signatures resolve, and resolve uniquelytools/pe/aob_scan.py, 4/4
FName::FName at RVA 0x36fd000signatures/FName_Constructor.lua
GUObjectArray at RVA 0x379bfc0signatures/GUObjectArray.lua
FUObjectHashTables::Get() at VA 0x1436800b3signatures/GUObjectHashTables.lua
ProcessLocalScriptFunction at RVA 0x394e460signatures/ProcessLocalScriptFunction.lua
The tag corpus grew to 12,292 tags; 12,290 parse and pass every structural checkmjolnir validate --all
The 101-group sample re-serialises byte for bytemjolnir roundtrip
The tag definitions are unchanged from CU2 — 101 groups, 1,779 structs, 13,250 fields, identicalmjolnir defs, corpus diff
The lock round-trips: 252 files hashed, snapshot verifies 252/252game_snapshot.py verify
CU3 recovered from the depot history hashes identical to its lock, 252/252steam_depot_fetch.py, manifest 457322918737678760

Verified in the running game (CU4, 2026-08-18):

ClaimEvidence
All 13 mods load with zero Lua errorsUE4SS.log
The in-game bridge answers at the frontend and in-missiongame_status ping
Campaign resume works; mission A30 loads and playsbridge world report
blam-live finds a loaded tag payload in memory and reads its live valuemjolnir poke --locate-only: spartans biped located, jump velocity reads 2.3 = shipped

defs/hce/tag-definitions.json and defs/hce/scripting.json are regenerated from the CU4 containers and stamped CU4 — the first corpus regeneration since CU2, which also retires the CU2-label caveat the previous revision of this note carried.

New tag content in CU4, per the CU3 → CU4 tagdiff: exactly one tag, the a10/unsc_cryo_capsule animation graph. The oddly named Cinematics/020la_sword/.../jorge_turret graph is present all the way back in vanilla CU2 — it is launch-era content, not update content. The two tags the full validation cannot parse fail identically on CU2, CU3 and CU4 — a long-standing decoder gap, not an update regression (see the pipeline note's known issues).

What is still CU3-or-earlier-measured

These notes carry an older build stamp and have not been re-measured against CU4. Most describe file formats, which move far less often than code addresses — and the CU4 corpus validating 100% structurally is indirect evidence the container and tag layout notes still hold — but nothing here should be cited as CU4-verified: