- record #06-17-1/#06-17-2 closure, option A registry, attachAttribute removal and readonly binding
- record A2 save-shape change, no-ledger-entry cross-reference and the C-H unfixed list
- record Phase 7 reopen / 07-VERIFICATION.md invalidation and measured gate results
- migrate the top-level snapshot assertion to heroSave.attribute.values.hp
- add CoreState enemyContext.getBindedHero() regressions: same live attribute before/after load, no rebinding, across all compressions
- IHeroStateSave.attribute becomes IHeroAttributeSave<THero>; top-level modifiers removed
- HeroState.attribute is readonly and loadState delegates to attribute.loadState (never reassigns)
- delete attachAttribute from IHeroState and HeroState, and its only test case
- thin-delegate registerModifier/createModifier/createAndInsertModifier to the attribute registry
- loadEquipEffect mounts equipment modifiers with save=false so equipment bonuses only return via re-equip
- add #06-17-1 regressions: same attribute instance, bonuses kept, no double-count when type is registered
Task 0 becomes a resolved decision record (options marked historical, locked results in <record>): registry moves into HeroAttribute with HeroState thin delegation and clone() carrying it; attachAttribute deleted from IHeroState/HeroState plus its sole test, attribute made readonly so loadState never rebinds; equipment modifiers excluded from the attribute save via addModifier(name, modifier, false); IHeroStateSave.attribute becomes IHeroAttributeSave<THero> with top-level modifiers removed (no compat branch); #06-17-1/#06-17-2 regressions authorized; #06-17-3..8 registered only.
- add 06-17-SUMMARY.md with the 27-row measured table, measurement parameters, fixed side load breakdown, truthful Low-vs-High branch note and D-44 gate results
- register 06-TEST-FINDINGS.md #06-17-1 (HeroEquipment keeps the replaced attribute reference, so equipment bonuses are lost after hero.loadState; confirmed by a throwaway probe: atk 5 -> 0 at all three compressions)
- register WINDOWS.md entry #28 for the stage-1 minimum equipment seed deviation
- expand COMPRESSIONS to NoCompression / LowCompression / HighCompression so the matrix is 3 map counts x 3 compressions x 3 timing items = 27 rows
- keep measureCase, fixture build order, side load and 06-16 files untouched; still zero assertions
- one full run: 5 perf files / 45 tests passed, 0 WARNING/ERROR codes, saveablesReal.perf.ts (27 tests) in 379ms -- no case approaches the 30000ms testTimeout
- move root floors.json into packages-user/data-state/test/fixtures/ (byte-identical) and delete the root copy
- add saveablesReal.perf.ts: toFlat/clearCodes/registerTiles/createRealMapFixture with a one-shot compareWith baseline
- seed the minimum 1 equipment instance so HeroEquipsStore.loadState does not raise error 58
- 3 rows: save / load / round trip for 1 map x NoCompression, zero assertions
- D-06: equipment.test.ts code-147 case stays it.skip with a Chinese note that 147 is a reserved code, currently unreachable by design; no production code touched
- WINDOWS.md ids 25/26 marked fixed (open_count 13 -> 11); no new ledger entries
- getCouldEquipSlot tests empty === -1 so the first empty named slot wins instead of always replacing the first match
- un-skip the named-slot empty-preference case; canEquipTo string branch untouched