The monthly communal "Siege": a named boss camps outside town for 72h with
a single shared HP pool. This lands the model and the automatic lifecycle;
the player-facing bout command is W2.
- New tables world_boss + world_boss_contrib (own tables, outside the
saveAdvCharacter fan-out, so a char save can't clobber the shared pool —
the isolation adventure_shadow earns). Absent active row == no event; no
bootstrap.
- Boss sized to the town it will fight: tier from the MEDIAN combined level
of any-chat-active players (feedback_presence_is_any_chat, off
daily_activity), pool HP = arena per-bout HP × ~2 bouts/active player,
clamped [4,60] bouts. Floored at T3.
- Lifecycle rides the 1-min eventTicker (no net-new goroutine): auto-spawn
on the 1st of each UTC month (JobCompleted dedup) + resolve a lapsed
window as a survival. Operator override + the daily bout are W2.
- Resolution: defeat mints a bounty scaled by fights fought (not damage —
accessibility) + a consumable cache + one low-rate treasure roll each;
survival debits 20% of the community pot as a tribute (a pot sink). Both
close-outs are guarded on status='active' so they fire once.
- Announcements post to the games room (no-op when GAMES_ROOM unset).
Pure logic (median, tier bucket, HP scaling, pool subtract/clamp, payout
split) is unit-tested; euro/DM emission left thin per the repo's no-client
-stub convention. Combat golden byte-identical (never touches SimulateCombat);
full plugin suite green.
Claude-Session: https://claude.ai/code/session_017mEwUmmS7aQTP2NQXj6rUa