- drop DirectionMapper; new MapState(state); addLayer(alias)+setEventLayer; remove addHook().load()
- align removed getLayerByAlias/getLayerAlias to layerList/alias and setDynamicDirection to tile.setFaceDirection
- dispose stale codes 62/63/64/84/130 per Q1=A; keep 60/61
- tests: expect default events for transferToDynamic(keepEvent=false); setMapList does not dedup
- getMapData(x,y,w,h): end index lineStart+nw and buffer width*height (keep out-of-range zero padding)
- toStatic(keepEvent=false): reset reused static tile to default events via loadState({})
- cropPointEvents: reindex by new width; resize/resize2 sync indexer width; resize2 clears point events on same-size reset
- eventView.reset(): clear dirty counter so dirty() returns false after restoring reference
EnemyManager tests use a real TileStore with registered id<->num tiles; drop legacy bridge and *ById helpers (getPrefab/createEnemy take number|string); reusePrefab 2-arg; addPrefab dedupes by code only. Widen IEnemyManager.getPrefab signature to number|string (doc+impl). Flag tests align to loadState rebuilding field instances (d74cc35). Focused: 60/60 green.
- clone() now binds each cloned modifier to the clone, records its modifierName, mirrors the source save flag and recomputes the attribute, matching addModifier's bookkeeping
- a cloned attribute can enumerate, index and persist its modifiers, and a cloned modifier's setValue notifies the clone
- add the bookkeeping and save-ability regression cases
- compareEquip clones each compared item's modifier before adding it to the comparison clone and removes the same clone objects afterwards
- the live attribute's already-bound modifiers never enter the clone and are never unbound
- add the equipped-item diff regression case (both directions, no warning 108, live bookkeeping untouched)
- add private clearDynamics() that snapshots the managed dynamic tiles and drops each via the deleteDynamic semantics (syncStaticEvent + removeTile + onDeleteDynamic), without awaiting the hook
- call it as the first line of loadState so all three compression tiers and the missing-dynamicBlocks case start from a clean slate (#06-17-8)
- add regressions: mapLayer hook/instance witness and the three-tier repeated-load non-accumulation case
- measureCase sampling loop now pairs mark(startTag)/mark(endTag) with
measure(measureName, startTag, endTag) and clears marks/measures per sample
- tag names derive from caseName+scale so they never collide across cases
- WARMUP_RUNS/SAMPLE_RUNS/median/min/p95/toFixed(3)/columns unchanged