{
  "kind": "hwanse-non-palette-motion-producer-review",
  "status": "battle-motion-grounded-map-tile-motion-producer-unbound",
  "source": [
    "out/palette_pipeline_review.json",
    "out/map_animation_execution_boundary_review.json",
    "out/map_animation_live_buffer_writer_review.json",
    "out/map_animation_frame_script_tile_write_review.json",
    "out/map_animation_non_object_tile_write_root_review.json",
    "out/battle_helper_position_motion_review.json",
    "out/battle_effect_animation_pattern_review.json",
    "out/battle_effect_visual_assertion_review.json"
  ],
  "summary": {
    "mapConclusion": "Map-side non-palette visible tile motion is still unbound: live tile writer handlers exist, but no static path currently ties them to animated map roots/cells or the field tick route.",
    "battleConclusion": "Battle-side non-palette effect motion is substantially grounded through helper position/motion fields, spawn streams, and visual runner assertions, with the explicit boundary that it is not yet an original runtime pixel oracle.",
    "mapSummary": {
      "animatedMapCount": 5,
      "animatedCellCount": 1200,
      "liveBufferCandidateVmTileWriteRefCount": 6,
      "liveBufferAnimatedRootBindingCount": 0,
      "frameScriptTileWriteProducerFound": false,
      "nonObjectPromotedAnimatedProducerCommandCount": 0,
      "specializedLoopStrongCandidateCount": 0,
      "drawTimeVisibleMotionTransformFound": false
    },
    "battleSummary": {
      "helpersWithPositionOrMotion": 84,
      "helpersWithMotionStep": 34,
      "skillsWithHelpers": 96,
      "skillsWithEffectFrames": 92,
      "skillsWithExecutionRequirements": 52,
      "motionModelClassifiedRows": 52,
      "pixelOracleStatus": "not-original-runtime-pixel-oracle"
    },
    "recommendedNextStaticStep": "For map motion, inspect the animated-map load/update dispatcher or any caller that materializes opcode 0x58/0x6b/0x76 streams after resource load; do not continue from palette handlers or strict object frame scripts unless new refs appear."
  },
  "mapSurfaces": [
    {
      "area": "palette ramp/copy",
      "source": "palette_pipeline_review.json",
      "status": "palette-buffer-copy-apply-path-grounded",
      "finding": "The EXE keeps a mutable 256-entry palette buffer at 0x004676e8. Palette effects copy or step RGB bytes inside that buffer, then push a range to DirectDraw with SetEntries. This is a color/fade/ramp pipeline, not proof of tile-position animation.",
      "promotion": "promoted-color-only",
      "boundary": "색상/fade/ramp 근거이며 타일 위치/source-index motion 근거는 아니다."
    },
    {
      "area": "live layer0/layer1 buffer writers",
      "source": "map_animation_live_buffer_writer_review.json",
      "status": "live-buffer-writers-grounded-animation-producer-unbound",
      "finding": "live layer0/layer1 buffer writer handlers are grounded, but their refs are not inside animated-map resource roots and no per-map/per-tick animation producer has been found. Keep visible map animation unpromoted.",
      "promotion": "handlers-grounded-root-unbound",
      "boundary": "opcode 0x58/0x6b/0x76 live tile writer는 확인됐지만 animated map root/tick와 연결되지 않았다."
    },
    {
      "area": "draw-time tile transform",
      "source": "map_animation_draw_tile_transform_review.json",
      "status": "draw-time-tile-transform-negative-for-visible-animation",
      "finding": "The inspected draw path maps the current live layer0 tile id to a source rect by fixed grid math. It does not provide the missing fire/waterfall frame loop.",
      "promotion": "negative-for-visible-motion",
      "boundary": "현재 draw path는 live layer0 tile id를 고정 grid 공식으로 source rect에 매핑한다."
    },
    {
      "area": "field tick route",
      "source": "map_animation_tick_route_review.json",
      "status": "tick-route-grounded-producer-still-indirect",
      "finding": "The field tick/update route is grounded, but it does not directly mutate live map buffers. The remaining static producer candidate is an active-object delayed script executed through 0x00402321.",
      "promotion": "tick-route-grounded-producer-indirect",
      "boundary": "per-frame route는 확인됐지만 직접 live map buffer를 mutate하지 않는다."
    },
    {
      "area": "strict active-object +0xec scripts",
      "source": "map_animation_active_object_script_tile_write_review.json",
      "status": "strict-active-object-script-tile-write-not-found",
      "finding": "No strict active-object +0xec script currently decodes to a command-boundary live tile-write. Raw plausible bytes exist only as unpromoted candidates if present.",
      "promotion": "negative",
      "boundary": "strict object script command boundary에서는 live tile write가 나오지 않는다."
    },
    {
      "area": "runtime-installed object +0x64 frame scripts",
      "source": "map_animation_frame_script_tile_write_review.json",
      "status": "object-frame-script-tile-write-not-found",
      "finding": "Runtime-installed object +0x64 frame scripts are grounded, but neither opcode 0x20 attach targets nor opcode 0x18 state-table entries contain command-boundary live map tile writes.",
      "promotion": "negative",
      "boundary": "opcode 0x20 attach target과 0x18 state-table entry 모두 command-boundary tile write가 없다."
    },
    {
      "area": "non-object aligned tile-write roots",
      "source": "map_animation_non_object_tile_write_root_review.json",
      "status": "non-object-tile-write-root-producer-not-found",
      "finding": "Aligned tile-write VM roots exist, but none both bind to a known animated map root and write a known animated tile/coordinate. The non-object/root scan therefore does not promote the visible fire/waterfall producer.",
      "promotion": "roots-exist-no-animated-binding",
      "boundary": "aligned tile-write commands는 있지만 animated map/root + animated coordinate/tile을 동시에 만족하지 않는다."
    },
    {
      "area": "specialized loop scan",
      "source": "map_animation_specialized_loop_boundary_review.json",
      "status": "specialized-map-animation-loop-not-found",
      "finding": "No inspected tick/redraw/draw window, nor its direct callees, exposes a separate live-buffer/tile-shift producer. The static evidence still stops at redraw invalidation plus generic writer handlers; continue from the animated-map load/update dispatcher.",
      "promotion": "negative",
      "boundary": "tick/redraw/draw 주변 direct callee에서도 별도 live-buffer/tile-shift producer를 찾지 못했다."
    }
  ],
  "battleSurfaces": [
    {
      "area": "helper position/motion fields",
      "source": "battle_helper_position_motion_review.json",
      "status": "helper-position-motion-field-review",
      "finding": "84 helpers carry position/motion; 34 carry motion step.",
      "promotion": "promoted-helper-motion-semantics",
      "boundary": "전투 helper/object motion은 팔레트가 아니라 object position/motion field 기반으로 해석 가능하다."
    },
    {
      "area": "effect pattern join",
      "source": "battle_effect_animation_pattern_review.json",
      "status": "effect-helper-animation-patterns-joined-by-skill",
      "finding": "96 skill rows have helpers; 52 rows require spawn/motion execution.",
      "promotion": "joined-by-skill",
      "boundary": "스킬별 helper/effect frame 결합은 됐지만 원작 픽셀 오라클은 별도 검증이다."
    },
    {
      "area": "visual execution assertions",
      "source": "battle_effect_visual_assertion_review.json",
      "status": "visual-assertions-pass",
      "finding": "52 requirement rows have colored previews; pixel oracle status is not-original-runtime-pixel-oracle.",
      "promotion": "web-runner-asserted-not-original-oracle",
      "boundary": "웹 runner 표현은 검증됐지만 원작 런타임 캡처와 동일하다고 주장하지 않는다."
    },
    {
      "area": "motion boundary loops",
      "source": "battle_motion_boundary_loop_review.json",
      "status": "motion-boundary-loop-semantics-grounded",
      "finding": "7 boundary rows, helpers [95, 96, 97, 98].",
      "promotion": "promoted-loop-semantics",
      "boundary": "일부 화면 경계/loop형 motion은 정적 분석으로 의미가 확정됐다."
    }
  ],
  "promotionDecisions": [
    {
      "area": "field map palette effects",
      "decision": "promote as color/ramp only",
      "reason": "palette buffer/copy/SetEntries path is grounded, but it cannot by itself move waterfall/fire source tiles."
    },
    {
      "area": "field map visible tile motion",
      "decision": "keep unpromoted",
      "reason": "no static producer writes animated-map live layer0 source ids under a proven per-map/per-tick binding."
    },
    {
      "area": "battle effect helper motion",
      "decision": "promote for runner use",
      "reason": "helper position/motion opcode fields and spawn/motion execution requirements are joined by skill and checked by visual assertions."
    }
  ],
  "nextFrontier": [
    "Search upstream materializers for tile-write command streams instead of re-scanning decoded +0xec/+0x64 object scripts.",
    "Separate map tile source-index motion from palette-only effects in every future map animation claim.",
    "If static search remains saturated, use a narrow runtime watchpoint on 0x00595af0 live layer0 entries for map1_01a/map1_02b animated cells.",
    "For battle effects, future work should target original-runtime pixel/oracle comparison rather than reclassifying already joined helper motion rows."
  ]
}
