Vigil
← All news

v0.15.0 — ### Added

- **T-103** Phase segmentation (boss-side). `analysis/phases.py::detect_phase_boundaries(session, fight_id)` derives per-fight phase intervals from enemy-actor damage-activity win…

  • T-103 Phase segmentation (boss-side). analysis/phases.py::detect_phase_boundaries(session, fight_id) derives per-fight phase intervals from enemy-actor damage-activity windows: each distinct non-player target's [first_hit, last_hit] window is a phase, with overlapping windows merging into one phase (handles FRU P4's two concurrent boss models). Default min_hits=30 filters trivial adds; default merge_gap_ms=0 (overlap-only) preserves real phase boundaries that have small transition gaps.
  • GET /api/fights/{id}/phases returns {phases: [{index, start_ts, end_ts, start_offset_ms, end_offset_ms, boss_target_ids, hit_count}], transitions: [{after_phase, gap_ms}]}. Offsets are relative to phase-0 start so the UI can render without absolute timestamps.
  • React PhaseStrip component in PullDetail — color-coded horizontal bar with one segment per detected phase (width proportional to phase duration), hover tooltip shows boss-target IDs + phase duration, transition gaps listed beneath.
  • 8 new tests (6 unit + 2 API). 137 tests total.
  • Live AC against FRU kill #163 (1097s): detected exactly 6 phases matching the encounter's known structure — P0 Fatebreaker (144s) → P1 Usurper of Frost (185s) → P2 Adds intermission (1393+1395 merged via overlap, 43s) → P3 Oracle of Darkness (161s) → P4 Pandora's Knight + Athena (1421+1424 merged, 165s) → P5 Fatebound (193s). Transitions 4.5s / 22.2s / 27.8s / 5.8s / 77.4s match FFXIV cutscene timings.

Changed

  • Pulled events for one FRU kill fight (report 4RVNq7drBDLG3JZw, fight DB-id 1500) so we have multi-phase dev data — the older FRU report YAtzbP6RBrcnTg2j is paywalled (archived). Dev DB now carries 29.7k events for the FRU kill.

Known

  • ingest_report flushes but does not commit; callers must session.commit() themselves. Caught this re-ingesting FRU when a TypeError in a subsequent call rolled the session back. Worth a docstring note or a refactor next time the function changes.
  • T-004's combatant filter is too permissive on Ultimate reports — pulled 2.5M combatants across 208 FRU fights (~12k per fight) because non-player NPCs are leaking through. Doesn't break analysis (queries always filter by player_id from the table), but bloats storage. Tracked informally for now.