High-priority fixes from the multi-agent audit of Adventure 2.0:
- Phase 11 nil-deref cluster: zoneOrFallback() helper replaces 8 unsafe
getZone(_) sites in dnd_zone_cmd.go. Corrupted zone IDs render a
placeholder instead of panicking.
- Briefing/recap idempotency: deliverBriefing/deliverRecap now claim
the rollover via a conditional UPDATE. Double-fires from clock skew
or restart become no-ops; supply burn and day++ no longer reapply.
- Graceful ticker shutdown: AdventurePlugin gains stopCh + Stop(); all
11 background tickers now select on stopCh in addition to ticker.C.
- Mood decay (§3.2): math.Round(elapsed*2) replaces int() truncation
so sub-hour gaps decay correctly.
- 24h auto-abandon (§4.3): getActiveZoneRun returns clean slate and
abandons stale runs whose LastActionAt is over 24h old.
- Respec / auto-migrate orphan cleanup: !respec and the auto-migrated
draft wipe now abandon active zone runs and expeditions before
deleting the dnd_character row.
- Phase R combat-link: applyBossDefeatThreat now wired from
resolveBossRoom (-20 threat); applyRoomCombatThreatForUser adds
+5/+8 from non-boss/elite kills (§8.1).
- Starvation → forced extraction: briefing-time check forces extract
with §10.2 coin tax when supplies hit zero.
- GMNat20/Nat1 narration wired into resolveCombatRoom and
resolveBossRoom (nat-20 takes precedence over nat-1).
- Treasure-undo race: LoadAndDelete on both timer-fire and `undo`
paths so only one side wins.
- Battle Master: Disarming, Menacing, Parry maneuvers added (3 → 6
of 10). Remaining 4 (Pushing, Goading, Riposte, Commander's Strike)
documented inline as needing ally/reaction mechanics the engine
doesn't model.
- Threat-70 warning: tracked in RegionState["siege_warning_fired"]
so a drop-and-recross doesn't re-fire the beat.
- region_state JSON decode error now logged via slog.Warn instead
of silently discarded.
Failing TestProdDB_DnDLayer fixed via option (a): track migrated
characters and only run round-trip / idempotency assertions on those,
skipping pre-existing prod-DB rows accumulated from live bot use.
New tests in dnd_audit_phase_R7_test.go cover: 24h auto-abandon,
briefing double-fire idempotency, threat-70 warning idempotency,
multi-region extract→resume state preservation, and starvation
forced-extraction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Underdark + Feywild Crossing (T4) and Dragon's Lair + Abyss Portal (T5)
registered. Zone hooks, atmosphere, factions, and boss descriptions
reuse the prewritten flavor in gogobee_dungeon_zones.md §5.
New bestiary entries:
Underdark: drow, drow_elite_warrior, drow_mage, mind_flayer,
hook_horror, roper, boss_ilvaras_xunyl
Feywild: redcap, will_o_wisp, quickling, night_hag, fomorian,
boss_thornmother (reuses Tier 2 green_hag)
Dragon's Lair: kobold, guard_drake, kobold_scale_sorcerer,
dragonborn_cultist, young_red_dragon, boss_infernax
Abyss Portal: quasit, vrock, hezrou, nalfeshnee, marilith,
boss_belaxath
Boss-entry pools (BossEntryInfernax, BossEntryBelaxath) and per-zone
RoomEntry pools for Underdark + Dragon's Lair already live in
twinbee_gm_flavor.go from a prior phase and are wired in
dnd_zone_narration.go — no narration switch changes here. Feywild and
Abyss room/boss/elite flavor lands in D5b.
Bumps TestBestiaryByCR cap from CR≤20 to CR≤30 to cover Infernax (CR
24, Ancient Red Dragon). New T4/T5 presence tests added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Haunted Manor of Blackspire + The Underforge registered. New bestiary
entries (poltergeist, banshee, wraith, vampire spawn, revenant,
Aldric Blackspire boss; magmin, azer, salamander, fire elemental,
helmed horror, Emberlord Thyrak boss) per dungeon zones doc §5.
Manor reuses Tier 1 shadow; Underforge reuses Tier 1 flameskull.
Manor Blackspire RoomEntry pool already lives in
twinbee_gm_flavor.go and is wired in dnd_zone_narration.go from a
prior phase, so no new flavor file is needed for that zone in D4a.
L1 tier-gate test bumped 4→6 now that T3 is visible to T1 players.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Forest of Shadows + Sunken Temple of Dar'eth registered. New bestiary
entries (dire wolf, bandit captain, owlbear, corrupted dryad, displacer
beast, green hag, kuo-toa + whip, water elemental, merrow, aboleth thrall,
Hollow King boss, Dreaming Aboleth boss) per dungeon zones doc §5. L1
tier-gate test expectation bumped from 2→4 zones now that T2 is visible
to T1 players.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zone Infrastructure SUB-A: ZoneDefinition / ZoneTier / ZoneEnemy /
ZoneBoss / ZoneLootEntry types and dndZoneRegistry. Tier 1 zones
populated per gogobee_dungeon_zones.md §5: Goblin Warrens (T1, L1-3,
boss Grol the Unbroken CR3) and Crypt of Valdris (T1, L1-3, boss
Valdris the Unburied CR5, phase 2 at 50% HP).
Helpers: getZone, zonesForLevel (2-tier-above ceiling), zonesByTier,
allZones.
Bestiary additions for Tier 1 enemy rosters: goblin_sneak,
goblin_archer, hobgoblin_grunt, worg, goblin_shaman,
hobgoblin_warchief, zombie, shadow, specter, wight, flameskull, plus
the two zone bosses. Zombie AC bumped 8->10 to satisfy engine
TestBestiaryAllWellFormed minimum.
7 new tests covering registry presence, bestiary-ref resolution, boss
CR floor, level-tier gating, loot-chance bounds, room-count sanity,
elite flag presence, and tier->level-range alignment. Full plugin
suite green.
Also marks SUB3 done in gogobee_subclass_system.md (all 15 subclasses
through L15 shipped across SUB3a-d).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>