Hot Seat is a room-scoped, opt-in bluffing game. It is wired as an independent plugin but is disabled by default. Startup inserts a disabled room configuration and ten approved English starter prompts when absent. Existing configuration, enabled state, prompt edits, and moderation decisions are preserved.
The game evaluates a respondent’s private truth/bluff declaration against
participants’ votes. It does not verify whether an answer is factually true. The
respondent writes their own answer in room chat; the bot never receives, copies,
logs, or stores that answer or a transcript.
Only current BC room administrators can change the configuration. Before enabling, the administrator must confirm that the room’s policy makes this an adults-only, opt-in activity. The bot does not infer, verify, or collect age.
Use native /bot commands or a private Whisper; chat and emote command forms are
rejected so mode declarations and votes are not exposed:
/bot hotseat config show
/bot hotseat config enable confirm-adults-only <revision>
/bot hotseat config set minPlayers 3 <revision>
/bot hotseat config set minVotes 2 <revision>
/bot hotseat cancel
/bot hotseat config disable <revision>
Global and scoped help show Hot Seat commands only while the room config is enabled. While disabled, that also hides the admin setup/configuration help; the commands remain registered so room admins can use the documented paths to enable it.
Every write supplies the current configuration revision and uses a compare-and-
set update. The first write uses revision 0. A conflict writes nothing; inspect
the latest revision and retry. The Mongo adapter shares only the revision-CAS
and optional-field clearing
mechanics with Staged Table; this feature retains its own config/session
validation and room isolation.
Settings are strictly validated:
| Setting | Default | Bounds |
|---|---|---|
minPlayers |
3 | 3–12 |
maxPlayers |
12 | 3–12 and at least minPlayers |
answerWindowMs |
120000 | 30000–300000 |
voteWindowMs |
90000 | 30000–300000 |
minVotes |
2 | 1 through maxPlayers - 1 |
bluffMultiplier |
2 | 2–3 |
refusalPolicy |
no_penalty |
no_penalty, forfeit_available |
timeoutPolicy |
no_penalty |
no_penalty, forfeit_available |
An active round keeps its saved settings and configuration revision; admin
changes apply to the next round. A room administrator may disable future rounds
without changing an active round. /bot hotseat cancel releases an abandoned
lobby only; it cannot cancel a started round.
Trusted operators manage prototypeHotSeatPrompts directly in the selected,
isolated runtime database. There is no in-game prompt authoring command. The
repository validates each document and selects only moderationStatus: "approved"
prompts with locale en; a missing or malformed approved prompt fails closed.
Prompt text is limited to 250 characters. Records also require a bounded prompt
ID, category, locale, positive contentRevision, and createdAt / updatedAt
dates.
Review prompt content before setting it approved. Prompts must be appropriate for the adults-only room and must not request identifying, non-consensual, or otherwise unsafe personal disclosures. The bundled starter catalog uses non-explicit romantic-comedy scenarios and preferences suitable for truth/bluff declarations. Use the party-game provisioning workflow for dry-run-first population and explicit adults-only activation.
/bot hotseat join. This creates or joins a
room lobby; the bot is never eligible./bot hotseat start. The command checks
the enabled room config, current room presence, player bounds, and approved
prompt availability. It freezes the current opted-in roster and randomly
selects one respondent and one approved prompt./bot hotseat mode truth or
/bot hotseat mode bluff. The respondent may instead privately run
/bot hotseat refuse./bot hotseat vote true or /bot hotseat vote lie. Each can submit one vote;
it cannot be changed. Departed voters cannot vote while absent, and new
arrivals are not part of the round.minVotes voids the vote without an
economic outcome. A strict lie majority exposes a declared bluff; a tie or
true majority means the bluff fooled the room. A declaration of truth
receives no bluff reward or forfeit. The result is described as a room vote,
never as fact verification.If the respondent leaves before declaring or refuses, the round closes without
collecting their answer. Refusal and response timeout have independent policies;
both default to no penalty. A configured forfeit_available timeout/refusal
clears only available credits. Voters receive no reward.
An administrator can cancel an abandoned lobby before a round starts. Lobby membership is refreshed against current BC room observations when a participant joins or starts, so departed lobby members do not reserve player slots.
The shared EconomyPort owns accounts and ledger entries. An exposed bluffer
forfeits available credits only; reserved credits from unrelated games remain
untouched. A fooled bluffer receives the configured multiplier reward, bounded
by a hard available-credit ceiling of 100,000. The ceiling is enforced
atomically by the economy repository. A zero or ceiling-blocked award is
reported as not applied, not as a successful payout. Stable operation IDs make
settlement retries idempotent.
| Collection | Owner | Retention |
|---|---|---|
prototypePartyGameConfigs |
Hot Seat repository for <roomKey>:hot-seat |
Revisioned room config; no TTL |
prototypeHotSeatPrompts |
Trusted operator | Operator-managed; no TTL |
prototypeHotSeatSessions |
Hot Seat repository | Active sessions have no TTL; terminal sessions expire after 30 days |
prototypeEconomyAccounts / prototypeEconomyLedger |
Shared economy | See the economy guide |
Session records contain a bounded member-number roster, selected respondent, prompt ID/revision, pinned settings revision, phase/revision, private intent, bounded votes, deadlines, outcome, and settlement operation metadata. They do not contain answer text, prompt text, or chat transcripts. A unique active-room key and revision-checked transitions prevent concurrent rounds and stale callbacks from advancing the same round twice. Deadlines are persisted; unref’ed timers are canceled on shutdown and rebuilt from active sessions at startup. Pending settlement is retried with the same operation ID after restart.
flowchart LR
Root["start.ts"] --> Plugin["HotSeatPlugin"]
Plugin --> Commands["HotSeatCommandSuite"]
Plugin --> Service["HotSeatService"]
Commands --> Service
Service --> Repo["MongoHotSeatRepository"]
Service --> Economy["EconomyPort"]
Commands --> PrivateReply["Injected private-reply capability"]
Repo --> Config[("prototypePartyGameConfigs")]
Repo --> Prompts[("prototypeHotSeatPrompts")]
Repo --> Sessions[("prototypeHotSeatSessions")]
stateDiagram-v2
[*] --> Lobby: enabled + explicit joins
Lobby --> Response: min current players + approved prompt
Response --> Voting: private truth/bluff declaration
Response --> Complete: no-penalty refusal / departure / timeout
Response --> Settling: configured refusal or timeout forfeit
Voting --> Voting: one private vote per eligible participant
Voting --> Complete: deadline below quorum / truthful declaration
Voting --> Settling: quorum resolves declared bluff
Settling --> Complete: idempotent economy result recorded
Settling --> Settling: restart retries same operation
Complete --> [*]
The service persists the terminal round outcome before settlement. The economy operation uses a stable session-derived ID; a restart retries that same operation and cannot forfeit or grant twice.