Adds IMissionProgressService to RankBattle, FreeBattle, ArenaTwoPickBattle, and
ArenaTwoPick controllers. Each finish handler emits the appropriate
MissionEventKeys builder result:
- RankBattle.Finish (win) → Ranked.WinAll(classId)
Includes AI-rank routes; on a private server AI wins count the same.
- FreeBattle.Finish (win) → Free.WinAll() (aggregates only)
- ArenaTwoPickBattle.Finish → Challenge.MatchPlayAll or MatchWinAll
Always fires challenge_play; wins additionally fire challenge_win and
the ranked/arena/daily aggregates.
- ArenaTwoPick.Finish (5-win full clear) → Challenge.FullClearAll
Gated on RunFinishOutcome.WasFullClear from the previous commit.
This closes six of the eight remaining catalog wire-up gaps; class_level_up
and rank_achieved follow in Tier 2 (need pre-state detection).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- FreeBattleController.Finish (rotation + unlimited URLs) now grants
win/loss XP via IBattleXpService with BattleXpMode.Free.
- Preserves the strict field subset (no rank/master fields).
- Tests updated: win asserts XP+level-up; new loss test on rotation URL.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>