Combat: guard daily-cron paths against mid-fight combat sessions

A turn-based elite/boss combat session locks the run for up to 1h and
can straddle any scheduled tick. Add hasActiveCombatSession() and consult
it from the morning DM, midnight idle reaper, expedition briefing/recap,
and mid-day random event paths so none of them fire DMs or mutate run
state into a live fight.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-14 08:01:10 -07:00
parent 146924818d
commit c84682abf7
5 changed files with 92 additions and 5 deletions

View File

@@ -138,6 +138,34 @@ func TestListExpiredCombatSessions(t *testing.T) {
}
}
func TestHasActiveCombatSession(t *testing.T) {
setupZoneRunTestDB(t)
uid := id.UserID("@combat-guard:example.org")
defer cleanupCombatSessions(uid)
if hasActiveCombatSession(uid) {
t.Fatal("no session yet, want false")
}
s, err := startCombatSession(uid, "r", "n", "boss", 60, 60, 120, 120)
if err != nil {
t.Fatal(err)
}
if !hasActiveCombatSession(uid) {
t.Error("active session, want true")
}
// A terminal session no longer counts as active.
s.Status = CombatStatusWon
s.Phase = CombatPhaseOver
if err := saveCombatSession(s); err != nil {
t.Fatal(err)
}
if hasActiveCombatSession(uid) {
t.Error("session is won, want false")
}
}
// ── State machine ──────────────────────────────────────────────────────────
// turnSession builds an in-memory CombatSession for state-machine tests that