Main's generated PlacedAgentAdapter always wrote `weapon` (WeaponType, typeId 38) at field 7, and StrategyPage legacy slots 4 (agents) and 11 (legacy LineUps) carry PlacedAgents. 3.2.3 has no typeId 38, so it could not open a page this build had saved. - PlacedAgentAdapter (typeId 2) is hand-written: it omits field 7 when the weapon is none, so an unarmed agent is byte-for-byte the 3.2.3 record, and still reads field 7 from desktop 4.6 libraries. - StrategyPageAdapter writes weapon-stripped copies into slots 4 and 11. The agents mirror (13) and lineup graph mirror (19) keep the real weapons, so this build restores them losslessly. - Audit of everything reachable from slots 0-11 and 14: only PlacedAgent.weapon was newer than 3.2.3. Text, images, utilities, settings, filtered drawings, PlacedAbility, LineUp and StrategyData write only primitives, Offset, Color, AbilityInfo and 3.2.3's types. Newer enum values (e.g. UtilityType) decode to 3.2.3's default rather than failing. - The generator prunes yaml rows for types it does not generate, so the hand-written typeIds (2, 3, 9, 11, 12, 17, 20, 24, 31) are now listed in @GenerateAdapters(reservedTypeIds:) and can never be reassigned. Tests: the rollback test decodes pages and a whole StrategyData with a registry holding exactly 3.2.3's adapters (field bags, byte enums, Color/TimeOfDay), plus a control proving it rejects an armed agent. The registry layout test checks weapons survive the round trip through the mirror while the legacy slots hold none. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Dara Adedeji committed on 9/24/2026, 8:51:40 PMparentf238037
7 files changedLine totals unavailable