# Battle Skill Timeline Goal

## Goal Command

```text
/goal 전투 스킬 타임라인을 EXE 근거 기준으로 전면 재검증한다. 주인공/몬스터의 모든 기술에 대해 skillId, payload, display VM 시작점, 프레임 시퀀스, gate, 이동/위치 opcode, hit window, WLK 호출 순서를 EXE에서 다시 산출하고, 표시 테이블 기반/수동 관찰/과거 보정 데이터가 실제 EXE 근거와 충돌하면 제거하거나 비활성 근거로 격리한다. battle_skill_timeline_review, battle_formula_calculator, battle_simulator가 같은 canonical 데이터를 쓰도록 통합하고, 모든 기술이 "시각 정렬 확정 / 표시 테이블 기반 검토 / 미확정"으로 명확히 분류될 때까지 정리한다. 완료 전에는 이펙트 애니메이션 고도화로 넘어가지 않는다.
```

## Completion Rules

- Active battle pages must load `out/battle_skill_timeline_canonical.json` as the timeline authority.
- Browser playback must not use name-regex, manual observation, or old hand-authored fallback frame sequences when EXE timeline data is missing.
- Every player and monster action must carry an explicit evidence class:
  - `visual-confirmed`: visual timeline alignment is grounded by a named branch-family/override or monster descriptor visible-slot.
  - `display-table-review`: EXE display VM stream exists, but visual alignment still needs review.
  - `unconfirmed`: active playback must not pretend this is confirmed.
- `battle_skill_timeline_review.html`, `battle_formula_calculator.html`, and `battle_simulator.html` must use the same canonical player/monster timeline rows.
- `battle_skill_timeline_review.html` must expose browser-verifiable selected action state, and the known shifted-row regressions must pass `tools/verify_battle_skill_timeline_browser.py`.
- Before this goal is complete, run `tools/build_battle_skill_timeline_canonical.py`, `tools/verify_web_assets.py`, `tools/verify_battle_skill_timeline_browser.py` under Xvfb, `py_compile`, and `git diff --check`.

## Current Browser Gate

`tools/verify_battle_skill_timeline_browser.py` opens `battle_skill_timeline_review.html` in WebKit and verifies that the page itself renders the canonical raw/playback filmstrips for known regressions:

- Rinshan `0x05` 도발.
- Rinshan `0x06` 꼬챙이 꿰기.
- Rinshan `0x09` and `0x0c` 안면백조권.
- Ataho `0x2f` and `0x32` 맹호룬룬권.

Passing this browser smoke is necessary evidence for the timeline review page.
It is enough for the current EXE-derived timeline/canonical playback goal when
combined with the visual assertion report below.  It is not intended to prove
pixel-perfect parity with a captured original runtime.

The same browser smoke also selects every row with an EXE-derived helper
execution requirement from `out/battle_effect_animation_pattern_review.json`.
Those rows cover random/range placement, child-object spawn over time, child
motion loops, and palette-flash behavior.  This proves the rows are reachable
through the page and shared runner and expose browser effect diagnostics for
those buckets. Rows with CNS effect frames also pass a browser canvas non-empty
pixel guard in both the effect strip and the combined actor/effect preview
canvas, but this is still not a full pixel/particle choreography oracle.

`tools/build_battle_effect_visual_assertion_review.py` consumes that browser
smoke and builds `out/battle_effect_visual_assertion_review.json/html`.  The report asserts the 52
execution-requirement rows across random/range placement, child spawn timing,
child motion loops, and palette transforms.  Passing that report proves the web
runner visibly draws those EXE-derived effect classes.  This is the current
goal's browser-visible effect gate.  It still does not compare against original
runtime captures or exact RNG particle positions; that stricter check is a
separate future parity task.

`tools/build_battle_effect_pixel_oracle_plan.py` defines optional original
runtime capture work for final parity.  It keeps the full oracle scope at 52
effect-requirement rows and derives an 8-row first-pass capture set that covers
the known requirement/class/behavior buckets.  This is a handoff for stricter
visual comparison, not a blocker for the current EXE static-analysis/canonical
playback goal.

`tools/build_battle_effect_capture_checklist.py` turns that plan into an intake
checklist.  It expects optional local data at
`data/battle_effect_capture_manifest.json` and reports which original runtime
captures are ready for comparison.  The capture binaries themselves should stay
outside git, under `captures/` or another local path.

`tools/capture_battle_effect_web_reference.py` captures deterministic web-runner
preview frames for the same first-pass or full oracle rows.  It writes ignored
local PNGs under `captures/battle_effect_pixel_oracle/` and updates the ignored
manifest with `webReferenceCapture` paths.  See
`docs/BATTLE_EFFECT_WEB_REFERENCE_CAPTURE.md` for the exact command.  This
prepares the comparison input, but it is not original runtime evidence.

`tools/prepare_battle_effect_original_capture_dirs.py` creates ignored
row-specific original-capture inbox directories from the first-pass or full
oracle plan.  `tools/import_battle_effect_original_captures.py` then attaches
externally captured original-runtime PNG frame directories to the same ignored
manifest.  It accepts raw or sanitized row-id directories, can copy frames into
ignored `captures/`, and reports frame-count mismatches against the web
reference side before the pixel comparator runs.

`tools/compare_battle_effect_pixel_oracle.py` performs the optional local pixel
comparison once both original-runtime captures and web reference captures are
listed in the manifest.  It is dependency-free and currently supports
non-interlaced 8-bit PNG frame files/directories.  Its result must not be used
as the completion gate for this goal; it belongs to the future original-runtime
parity check.
`tools/verify_battle_effect_pixel_compare_selftest.py` uses temporary PNGs to
prove the comparator's pass/diff/frame-count/missing-input code paths work
without needing original captures.

## Current Boundary

The canonical bundle is intentionally limited to EXE-derived action timeline
evidence. Higher-level effect choreography can use helper/effect reports, but
should not override actor frame/gate/WLK rows until those rows are promoted into
canonical evidence.  Original-runtime screenshots or videos are useful for a
later visual parity pass, but they are not required to complete this EXE
canonical playback goal.
