| name | engine-bump |
| description | Respond to a Bannerlord engine update (Steam force-bump or deliberate migration) — preserve the decompile baseline, regen, diff, re-verify bindings and creature data, control-battle. |
Engine Bump Response
Run when the installed Bannerlord version changes — whether Steam force-updated under us (the
1.4.5 → 1.4.6 event, 2026-06-11 17:39, discovered a day late at the cost of a morning of
misattributed crashes) or we migrate deliberately. The session-start hook warns on drift
(pinned version in .claude/pinned-game-version.txt); this skill is the response.
Phase 1 — Confirm + scope the drift
- Installed truth:
bin/Win64_Shipping_Client/Version.xml + DLL LastWriteTimes (the update
timestamp bounds which test runs were on which engine — decisive for crash attribution).
- The wEditor build (Modding Kit) updates on its OWN Steam schedule — check its DLL dates
separately; it routinely stays a version behind (1.4.5-era while shipping was 1.4.6).
taom-src auto-detects the new version (fresh cache under ~/.taom-src/v<new>/) — old
caches remain but are unused.
Phase 2 — Preserve the baseline, THEN regenerate
Rename-Item "E:\Decompiled_Bannerlord\_shipping_build" "_shipping_build_v<OLD>" # BEFORE regen!
pwsh tools/decompile_bannerlord.ps1 # background; ~5-10 min; overwrites _shipping_build
The renamed baseline is what makes diffing possible — 1.4.5's lives at
E:\Decompiled_Bannerlord\_shipping_build_v1.4.5. The curated category folders
(MountAndBlade/ etc.) stay at the OLD version until separately regenerated — note the drift.
Phase 3 — Diff to scope the blast radius
Hash-compare every _shipping_build_v<OLD>\*.cs against the new _shipping_build\*.cs
(MD5 loop), then git diff --no-index the changed ones. Beware the ilspycmd version-nag line
appended to fresh output (false diff). 1.4.6 result for calibration: combat assembly
(TaleWorlds.MountAndBlade) + interop (AutoGenerated) byte-identical; only CampaignSystem/UI
moved → all gameplay changes were NATIVE-internal.
Phase 4 — Re-verify TAOM against the new engine
/verify-bindings — every Harmony patch / GameModel / reflection site.
python tools/audit_mount_parity.py — creature data vs the (possibly re-schema'd)
vanilla baselines.
python tools/audit_action_set_parity.py — resolves EVERY action_set's effective surface
(own actions + base_set chain + cross-module field-merge) and flags any HUMANOID set missing
part of Native's as_human_warrior (exit 1 if any). A new engine version can add action types to
as_human_warrior that a standalone set won't inherit → CTD on first use (the 1.3→1.4.6 dwarf
water-CTD: 423 types had drifted). For each gap the audit reports, fix with
python tools/patch_dwarf_action_parity.py --set-id <id> --apply (writes both the live LOTRLOME file
and the snapshot). The audit confirmed as_dwarf_warrior was the only humanoid gap (1110 humanoid
sets, 0 others). Creature mounts (spider/elephant/chariot) use a separate surface → audit_mount_parity.py.
- Vanilla data rescan per
.claude/rules/vanilla-data-comparison.md (scene renames/removals,
XML re-schemas) + check which vanilla ModuleData XMLs the update actually touched
(timestamp filter).
- Update the pin: write the new version into
.claude/pinned-game-version.txt (the file
session-start.sh reads; note it's .claude/, NOT .claude/state/).
- CLAUDE.md target-version note + memory update (needs explicit user OK for CLAUDE.md).
Phase 5 — Control battles before believing anything
Vanilla-only → warg → each TAOM creature, charging and meleeing. On any CTD, compare the
Windows Event Log fault offset against the previous version's known sites BEFORE assuming your
last change caused it (/native-crash-triage Phase 1) — the rewritten native lookups in new
engine versions turn previously-tolerated data misses into AVs
(memory: feedback_engine_lookup_total_key_coverage).
Worked example of the whole protocol: docs/features/spider.md "The v1.4.6 engine-bump
campaign" + CHANGELOG 2026-06-12.