veratown-prototype

Staged Table Game Proposal

Status: Chat and opt-in BC-avatar appearance flows implemented. This design adapts the staged pacing and shifting roles of the source concept into a consent-forward party game. Neither mode requests or verifies a physical action.

Appearance mode may remove explicitly selected clothing groups and apply non-locking, bondage-style avatar items to a participant’s own BC character. It is a visual game effect, not physical restraint. Activation is disabled by default and requires the bot-wide safeword, appearance reconciliation, revision-pinned stage/release validation, and recoverable timed cleanup described below. Operators remain responsible for controlled live BC qualification of their configured itemsets.

Recommendation

Add a disabled-by-default, room-scoped table game with a warm-up, a gradual wardrobe-marker track, and a late-game spotlight phase. Players voluntarily join each session and play a bounded card game for non-transferable score chips. Each player separately chooses chat-only play or pre-authorized, incremental appearance changes to their own BC character. Marker counts remain game state; only the separately opted-in appearance mode changes avatar state.

This preserves the source’s useful structure—an opening period with no consequences, an uneven progression, and a late phase that changes the game’s roles—without making a person’s body, clothing, or ability to refuse part of the wager.

Product scope and non-goals

The core feature is chat-only. Its optional appearance mode may change only the consenting participant’s BC avatar through the guarded appearance pipeline. It does not:

The first release is not a real-time poker client. It uses a bot-dealt, non-betting five-card draw with published ranking and tie rules. All cards are delivered privately; only the round result is public. This avoids depending on the bot observing a physical deck or on players disclosing private hands.

Session flow

  1. The room configuration must already be enabled by an operator. A room administrator may open a lobby early; otherwise, the first eligible join creates it automatically.
  2. The bot privately shows each joining player the complete rules, phase schedule, prompt policy, appearance plan and release deadline (if enabled), stop/leave behavior, and marker meaning.
  3. Each player joins once with /bot table join accept chat or /bot table join accept appearance. The appearance choice is explicit consent to the complete, disclosed progression and emergency-release plan; no later stage confirmation is required. Prompt invitations still require separate /bot table prompt enable consent. Room presence or prior participation is never consent.
  4. Joined players privately mark themselves ready. The game starts automatically when the configured minimum number of current-room players is present and every present joined player is ready. The administrator start command enforces the same checks. The roster is frozen for that session; arrivals can join a later session.
  5. Any participant can use the global /bot safeword at any time, without a reason or penalty. The session ends immediately, no further prompts are sent, and an unresolved hand is voided with its antes refunded.

Room policy should confirm an adults-only, opt-in activity before enabling the game. This is an operator attestation, not age verification. Every participant must still join the individual session.

2. Warm-up

The default warm-up lasts 60 minutes from the administrator’s start command. It is a configurable, bounded duration. Players play hands and collect non-transferable score chips, but no wardrobe markers or challenge invitations are issued. The host may offer one non-personal, passable icebreaker; it is not recorded.

If fewer than the configured minimum remain present, the game pauses between hands. It never deals to absent players.

3. Marker track

After warm-up, each losing player receives one generic wardrobe marker. Markers are game counters, not named garments. For a player in chat-only mode, the marker changes no BC state. For a player who accepted the complete appearance plan, a loss automatically advances their own avatar by one pre-approved appearance stage. The sequence is shown before consent, and stage count is capped. Players who opt out or leave appearance mode receive no new appearance changes and no gameplay penalty; leaving appearance mode immediately invokes emergency release for their own character.

Uneven marker counts are allowed and visible in the game’s public scoreboard. The first participant to reach the configured marker threshold may privately confirm /bot table spotlight to open the late-game phase. If they do not confirm, play continues normally. No player is automatically selected for a challenge or removed from play.

4. Spotlight phase

The phase changes only after an eligible participant explicitly confirms the spotlight transition. Participants who opted into prompts may draw from the reviewed, chat-only prompt catalog. Each prompt is delivered privately to its recipient, who can complete, pass, or stop the session. A pass has no consequence; the bot records only the prompt ID and a passed/completed attestation, not the response. An unanswered offer expires without consequence and is recorded as expired, not as a pass.

Optional late-game mechanics:

There is no “last clothed player” role, forced service, physical restraint, blindfold, or challenge based on another participant’s win or loss. Restraint items in appearance mode are non-locking BC-avatar visuals only.

Optional appearance progression

Appearance progression is independently disabled by default. Before the session starts, the participant privately reviews the complete sequence and the configured emergency.release.clothing set. The review names every clothing group that may be stripped, each stage’s revision-pinned itemset, the release set’s revision and effects, and the post-game cleanup delay. The one /bot table join accept appearance command opts in to both the game and that entire sequence. No participant is opted in by the room admin or by joining chat-only.

After warm-up, each non-tied hand loss automatically applies the participant’s next configured stage to that participant’s own character. The first post-warm-up hand that reduces a positive score-chip balance to zero also advances one stage; if both conditions occur on one hand, only one stage advances. This appearance progression is independent of the marker cap and voluntary spotlight threshold: losses can continue advancing stages after a participant reaches that threshold. Chat-only participants are never changed.

  1. Read the next entry from the room’s ordered appearanceStages plan. Its single stripGroup is the next clothing/equipment group to remove.
  2. Apply that entry’s revision-pinned itemset, which must strip exactly that group and may add only approved non-locking avatar pieces.
  3. Advance the stage counter only after the matching BC appearance observation.

The array order is the configured stripping order; the runtime must not sort groups alphabetically, by catalog order, or by a hard-coded clothing hierarchy. Each group appears at most once, is validated against the pinned BC catalog, and must also be covered by the disclosed emergency-release set. ItemNeck is forbidden. The accepted plan is pinned to each session so an admin edit cannot silently reorder an active game.

The sequence is bounded by the configured plan of at most ten stages. It is not a request for the player to perform an action; the change is entirely to their BC avatar. The dry-run-first party-game provisioner seeds six validated strip-only defaults (table.stage.set.one through .six) when applied. This does not enable appearance mode or seed the separately required emergency-release set. Every stage must use validated prototypeItemSets revisions. Sets containing lock selections, unsupported properties, or unapproved groups are rejected. Existing locked items, permission denials, unknown item state, target departure, or uncertain writes stop that participant’s progression; the bot does not bypass permissions or blindly retry. A player may use /bot table appearance stop at any time to end their own appearance progression and immediately invoke emergency release without leaving the card game.

The release set must cover every group used by the appearance stages. If its effects include groups outside the disclosed plan, appearance mode cannot be enabled until the set is narrowed or a suitable release set is configured. Because stripGroups operate on whole groups, a stage or release can remove the current item in an agreed group even if the game did not add it. The exact groups and release outfit are disclosed before opt-in. The participant’s full pre-game appearance is not snapshotted or restored. Participants can remove any item themselves at any time through BC. Neither the bot nor the game claims to verify real-world clothing or restraint.

5. End

The game ends when the administrator closes it, all participants leave, the configured session duration expires, or a participant invokes the stop command. The game may also end by a consented, bounded round limit. For appearance participants, natural end starts a persisted cleanup deadline: the existing emergency-release set is applied to each opted-in participant when that deadline arrives. A safeword ends the game and triggers that release immediately, without the delay. Leaving appearance mode also starts immediate cleanup for that participant. The bot publishes final score-chip totals and marker counts only; these values have no value outside the session. It does not rank or shame participants for opting out.

Solo play with simulated opponents

When soloEnabled is true, a player may start immediately without a lobby or room-admin action:

The session has one real player and the configured number of simulated seats (default three; bounded from two to five, for six seats maximum). Solo does not use the multiplayer minPlayers quorum. Simulated opponents are local game records, not BC characters: they have no member numbers, accounts, chat messages, prompt consent, or appearance changes. They cannot count toward multiplayer quorum, volunteer for roles, or satisfy a human-consent gate.

Opponent play is deterministic and code-owned, not an external AI service. Profiles rotate from a small fixed set: steady keeps a made pair or better and otherwise the three highest cards; draw-chaser keeps a four-card straight/flush draw or made pair and otherwise the three highest; loose keeps a pair or better and otherwise the two highest. All simulated hands use the same deck, ranking, chip, and tie rules as human hands. Results label them clearly as simulated; no opponent behavior or strategy history is persisted between sessions.

Solo mode disables room polls, peer-targeted prompt offers, and the steward role. If the human separately enabled prompts, only that human can receive an optional prompt and may pass or stop without penalty. Appearance progression, if selected, applies only to the human player’s character and uses the same opt-out and cleanup behavior as multiplayer.

Hand rules

Use a standard 52-card deck without jokers. At the start of each hand:

  1. In multiplayer, verify the frozen human roster against the current BC room observation and require the configured minimum number to be present. In solo, verify the single human participant; virtual opponents need no room presence.
  2. Each participant starts the session with ten score chips. Before the hand, each player antes one chip if they have one; a player with no chips may still play but does not ante.
  3. Shuffle with a cryptographically secure process-local random source and deal five cards privately to each present participant.
  4. Offer one simultaneous discard-and-redraw round. A player may keep all or discard up to three cards; commands accept only unique positions 1 through 5.
  5. Evaluate standard five-card poker rankings, highest first: straight flush, four of a kind, full house, flush, straight, three of a kind, two pair, one pair, high card. Compare rank-specific kickers lexicographically.
  6. If the best hand is tied, the hand is a push: no chips move and no markers are offered; the pot carries to the next hand. Otherwise, the sole winner takes the pot. Chips cannot go below zero and cannot be purchased, transferred, or redeemed.
  7. Publish only the winning rank and score-chip movement; do not reveal private cards. After warm-up, increment each non-winning participant’s marker count by one, up to the configured cap. A tied push adds no markers.

If a player leaves or fails to submit a discard choice before the deadline, void that hand, reveal no private cards, refund any antes, and make no score or marker changes. The implementation must not infer consent or completion from silence. The roster is capped at six players; the three-card discard cap keeps replacement draws within the remaining 52-card deck.

Commands and privacy

All commands use the existing /bot parser. Private replies are used for consent, private cards, discards, prompt offers, and prompt outcomes.

Command Behavior
/bot safeword Global, immediate stop for the current opted-in activity.
/bot table rules Privately show current rules and consent/stop behavior.
/bot table open Room-admin only; open a lobby for explicit joins.
/bot table join accept chat Join with chat-only mechanics.
/bot table join accept appearance Join and authorize the disclosed automatic appearance sequence.
/bot table solo start chat Start solo play against simulated opponents.
/bot table solo start appearance Start solo play with the single appearance opt-in.
/bot table prompt enable Separately opt into optional chat-prompt invitations.
/bot table prompt disable Withdraw prompt consent at any time.
/bot table appearance stop Opt out at any time; immediately invoke emergency release.
/bot table leave Withdraw from the session; immediately clean up own items.
/bot table start Room-admin only; freeze a valid roster and begin warm-up.
/bot table discard <positions> Submit one to three unique card positions privately.
/bot table discard none Keep all cards for this hand.
/bot table prompt accept Accept an offered prompt.
/bot table prompt pass Pass on an offered prompt without penalty.
/bot table prompt complete Privately attest completion without sending the answer.
/bot table spotlight Confirm a voluntary spotlight-phase transition.
/bot table steward accept Volunteer for the optional steward role.
/bot table steward leave Leave the optional steward role.
/bot table close Room-admin only; end the active session without penalty.
/bot table stop Alias to the global safeword behavior for this session.

The bot never requests a participant’s answer in chat. For an accepted prompt, completion is self-attested by a private command; the bot reports an attestation, not verified truth. Logs and session documents contain no freeform answers, prompt responses, or chat transcripts.

Configuration and persistence

Use one room-scoped config in prototypePartyGameConfigs with game ID staged-table, a disabled default, revision checks, and validated bounds. Proposed settings:

Setting Initial default Validation intent
enabled false Requires explicit operator activation.
adultsOnlyConfirmed false Required for activation; operator attestation only.
minPlayers / maxPlayers 3 / 6 Bounded roster; reject inconsistent bounds.
warmupMs 3600000 Bounded duration; default is one hour.
handWindowMs 120000 Bounded deadline for discards.
offerWindowMs 60000 Bounded response window for optional offers.
sessionLimitMs 21600000 Hard maximum session duration.
maxRounds 59 Per-game cap is min(setting, seats × 10 − 1).
markerLimit 4 Bounded fictional marker track and voluntary spotlight threshold.
spotlightPromptEnabled false Optional and disabled unless approved content exists.
appearanceEnabled false Enables only the separately consented avatar mode.
appearanceStages [] Up to ten ordered {stripGroup, itemSetKey, revision} steps.
restraintRemovalDelayMs 900000 0–3,600,000 ms after natural game end; safety stop is immediate.
soloEnabled false Enables single-human sessions.
soloOpponentCount 3 2–5 virtual seats; total seats capped at six.

Do not expose random seeds, arbitrary prompt text, executable rules, or unbounded durations through database configuration. Code owns the ranking, phase transitions, prompt safety ceilings, and stop semantics.

The operator provisioning workflow must add this game to its read-only plan, disabled-default insertion, adults-only confirmation, and explicit activation path before the feature can be enabled in a runtime. Appearance activation requires the complete validated stage/release plan and explicit participant consent; a database flag alone cannot guarantee successful BC actions.

prototypeStagedTablePrompts contains immutable, bounded, operator-reviewed prompt revisions with locale, category, revision, and moderation status. Approved prompts must be short, chat-only, non-explicit, and passable. They must not request identifying or intimate information, disclosure about another person, physical actions, external contact, images, or voice.

prototypeStagedTableSessions stores the room key, frozen bounded roster, consent flags, config/prompt revisions, phase, hand number, deadlines, current round state, score-chip totals, marker counts, steward opt-in, and terminal reason. Appearance participants additionally store their single consent decision, the ordered strip-group/itemset plan, the pinned emergency.release.clothing revision, current stage, and cleanup deadline/status. Do not persist full appearance payloads. Solo sessions store fixed strategy identifiers and virtual seat scores only; simulated opponent profiles do not persist across sessions. Private hands and pending discards are stored only in the session’s in-progress hand state, then deleted when the hand resolves or is voided. This allows safe restart recovery without dealing a replacement hand. Do not persist the deck shuffle seed, prompt responses, or freeform text. Active sessions have no TTL; terminal sessions may expire after 30 days.

Use revision-checked writes for concurrent commands and a unique active-room key to prevent overlapping sessions. Persist deadlines and recover sessions after restart without dealing a new hand or repeating a prompt. If recovery cannot establish a safe phase, stop the session with no score or marker penalty. Clear timers and listeners on completion and plug-in stop.

Global safeword, appearance application, and timed cleanup

The safeword is a shared bot safety primitive, not a game-specific prompt or a secret phrase stored in a session. /bot safeword must be available to any participant in an active bot-managed activity, including chat-only players, bypass admin checks and feature aliases, and stop the activity immediately without asking for a reason or confirmation. A stop transition is persisted before any ordinary notification; it cancels pending offers and timers, rejects new game actions, voids an unresolved hand with antes refunded, and bypasses the configured appearance-cleanup delay. It immediately invokes the existing emergency-release path for each appearance-opted-in member of that session. The command reports privately that the session stopped. A stopped session cannot be resumed; restarting requires a new lobby and fresh consent from every participant. Do not log the invoking message or expose publicly who called the safeword.

Each appearance step uses the existing guarded appearance itemset pipeline, through a narrow capability injected from the composition root. The current EmergencyReleasePlugin owns a self-service command and receives its set application callback from src/app/start.ts; make that callback a reusable release capability so the native command and game cleanup share one implementation and one journal owner. Do not invoke the plugin internally, synthesize a command, or import another feature. Every stage set and the emergency.release.clothing set must be enabled, catalog-validated, and pinned to its revision before the session starts. Stage mutations complete only from matching BC-observed appearance.

The emergency-release set’s full effect (its stripGroups and resulting pieces) must be shown before the one appearance opt-in. Its stripped groups must include every group used by the progression plan and must not affect undisclosed groups. Reject appearance mode if the release set is missing, changed, invalid, contains an unsupported lock, or cannot safely cover the progression plan. No stage or release set may contain a BC lock selection; ItemNeck is prohibited. Preserve all unrelated groups and current pose. Never persist full appearance payloads; session state stores only itemset keys and revisions, consent, stage number, and cleanup status.

The BC SafewordPadlock remains unsupported and has BC-owned semantics; it is not the bot safeword. The existing /bot emergency-release applies the configured clothing set, intentionally preserves ItemNeck, and may report partial or failed application. Its set must be qualified to remove every non-locking restraint-style item the game can add; it is not a generic bypass for locked or unsupported items.

On natural end, persist cleanupDueAt = endedAt + restraintRemovalDelayMs. Schedule an unref’ed timer and recover overdue cleanup after restart. At the deadline, invoke the pinned emergency-release set for every appearance-opted-in participant. The participant may invoke /bot emergency-release sooner. If a member is absent, disconnected, or BC rejects the mutation, leave cleanup pending, report the limitation privately when possible, and resume only after fresh BC observation; never claim cleanup completed without matching state. Since Veratown cannot act while offline, exact-deadline automation cannot be guaranteed during a disconnection. Disclose this limit and keep the wearer-controlled /bot emergency-release and native BC removal paths available at every moment. A safeword or appearance opt-out invokes release immediately and skips the hold period.

Appearance-stage application targets only a participant who accepted that complete sequence at join. Emergency-release cleanup may address only those same consented members and may only apply the pinned release set; it cannot apply new restraint assets. A dispatched write cannot be undone by the safeword, so appearance actions must honor cancellation before queue dispatch and reconcile any already-dispatched write from observed BC state.

UML, use cases, and state flows

Component diagram

flowchart LR
    Root["start.ts composition root"] --> Host["BotPluginHost"]
    Host --> Plugin["StagedTablePlugin"]
    Plugin --> Commands["StagedTableCommandSuite"]
    Plugin --> Service["StagedTableService"]
    Commands --> Parser["BotCommandParser"]
    Commands --> Service
    Commands --> Safety["Shared SafetyStop handler"]
    Safety --> Service
    Service --> Rules["StagedTableRules / PokerHandEvaluator"]
    Service --> Opponents["Local SimulatedOpponentStrategy"]
    Service --> Repository["StagedTableRepository"]
    Repository --> Config[("prototypePartyGameConfigs")]
    Repository --> Prompts[("prototypeStagedTablePrompts")]
    Repository --> Sessions[("prototypeStagedTableSessions")]
    Service --> Communication["Injected private/public communication"]
    Service --> AppearancePort["AppearanceItemSetPort"]
    Service --> ReleasePort["EmergencyReleasePort"]
    Root --> AppearancePort
    Root --> ReleasePort
    AppearancePort --> ItemSets["AppearanceItemSetService"]
    ReleasePort --> ItemSets
    EmergencyCommand["EmergencyReleasePlugin command"] --> ReleasePort
    ItemSets --> Actions["Guarded appearance actions"]
    Actions --> Coordinator["ActionCoordinator"]
    Coordinator --> Journal[("prototypeActions")]
    Actions --> BcClient["BcClient queue"]
    BcClient <--> BC["Bondage Club"]
    BC --> Observed["Inbound appearance observation"]
    Observed --> Service

The composition root injects narrow appearance and release capabilities. The game does not import the Appearance or Emergency Release feature, own a socket, or create a second journal owner.

Class diagram

classDiagram
    class StagedTablePlugin {
        +start()
        +stop()
    }
    class StagedTableCommandSuite {
        +openLobby()
        +join(mode)
        +startMultiplayer()
        +startSolo(mode)
        +discard(positions)
        +stopAppearance()
        +safeword()
    }
    class StagedTableService {
        +join(member, mode)
        +startMultiplayer(roomKey)
        +startSolo(member, mode)
        +resolveHand(sessionId)
        +handleSafeword(sessionId, member)
        +recover(roomKey)
        +stop()
    }
    class StagedTableRules {
        +validateConfig(config)
        +evaluateHands(hands)
        +nextAppearanceStage(plan, stage)
    }
    class SimulatedOpponentStrategy {
        +chooseDiscards(hand, profile)
    }
    class StagedTableRepository {
        <<port>>
        +createSession(session)
        +transition(sessionId, expectedRevision, next)
        +listRecoverable(roomKey)
    }
    class StagedTableSession {
        +mode
        +phase
        +roster
        +appearanceConsents
        +appearanceStagePlans
        +cleanupDueAt
        +revision
    }
    class AppearanceStage {
        +stripGroup
        +itemSetKey
        +itemSetRevision
    }
    class AppearanceItemSetPort {
        <<injected>>
        +applyStage(member, stage)
    }
    class EmergencyReleasePort {
        <<injected>>
        +applyRelease(member, pinnedRevision)
    }
    StagedTablePlugin --> StagedTableCommandSuite
    StagedTablePlugin --> StagedTableService
    StagedTableCommandSuite --> StagedTableService
    StagedTableService --> StagedTableRules
    StagedTableService --> SimulatedOpponentStrategy
    StagedTableService --> StagedTableRepository
    StagedTableService --> AppearanceItemSetPort
    StagedTableService --> EmergencyReleasePort
    StagedTableSession o-- AppearanceStage
    StagedTableRepository --> StagedTableSession

Use-case diagram

flowchart LR
    Admin((Room admin))
    Player((Participant))
    Operator((Trusted operator))
    BC((Bondage Club))

    Open([Open / close multiplayer lobby])
    JoinChat([Join chat-only])
    JoinAppearance([Join with one appearance opt-in])
    Solo([Start solo vs simulated opponents])
    Play([Play and discard cards])
    Prompt([Accept or pass optional chat prompt])
    Safeword([Stop active activity immediately])
    OptOut([Opt out of appearance and invoke emergency release])
    Cleanup([Apply delayed release set after natural end])
    Configure([Configure ordered groups, itemsets, and release delay])
    Observe([Synchronize and observe appearance result])

    Admin --> Open
    Player --> JoinChat
    Player --> JoinAppearance
    Player --> Solo
    Player --> Play
    Player --> Prompt
    Player --> Safeword
    Player --> OptOut
    Operator --> Configure
    JoinAppearance --> Play
    Solo --> Play
    Play --> Cleanup
    OptOut --> Cleanup
    Safeword --> Cleanup
    Cleanup --> Observe
    BC --> Observe

Simulated opponents are internal strategy records, not actors: they cannot join, consent, receive prompts, trigger appearance changes, or invoke the safeword.

Session state flow

stateDiagram-v2
    [*] --> Lobby: first eligible join or admin opens
    [*] --> Warmup: enabled solo start + one human
    Lobby --> Lobby: explicit chat / appearance join
    Lobby --> Lobby: participant marks ready / not ready
    Lobby --> Warmup: minimum present players; all present joined players ready
    Lobby --> Complete: admin closes lobby
    Warmup --> Warmup: hands; no markers or appearance stages
    Warmup --> Progression: warmup deadline
    Progression --> Progression: hand resolves; marker / next opted-in stage
    Progression --> Spotlight: threshold reached + participant confirms
    Spotlight --> Spotlight: optional prompt / continued hands
    Warmup --> Complete: natural limit / admin close
    Progression --> Complete: natural limit / admin close
    Spotlight --> Complete: natural limit / admin close
    Lobby --> SafetyStopped: safeword
    Warmup --> SafetyStopped: safeword
    Progression --> SafetyStopped: safeword
    Spotlight --> SafetyStopped: safeword
    SafetyStopped --> [*]
    Complete --> [*]

Appearance and release state flow

stateDiagram-v2
    [*] --> ChatOnly: join chat / solo chat
    [*] --> AppearanceReady: one appearance opt-in + pinned plan
    AppearanceReady --> AppearanceActive: first eligible post-warmup loss
    AppearanceActive --> AppearanceActive: next ordered stage observed
    AppearanceActive --> AppearanceActive: stage cap reached
    AppearanceActive --> CleanupWaiting: natural game end / persist dueAt
    AppearanceReady --> CleanupWaiting: natural game end
    AppearanceReady --> ReleasePending: appearance opt-out / leave / safeword
    AppearanceActive --> ReleasePending: appearance opt-out / leave / safeword
    CleanupWaiting --> ReleasePending: configured deadline reached
    ReleasePending --> Released: emergency release observed complete
    ReleasePending --> ReleasePending: absent / partial / uncertain
    ReleasePending --> Released: fresh observation confirms items absent
    ChatOnly --> [*]
    Released --> [*]

Solo-hand activity flow

flowchart TD
    Start([/bot table solo start chat or appearance]) --> Gate{Solo enabled and no active session?}
    Gate -->|No| Reject[Reply privately; create no session]
    Gate -->|Yes| Present[Show rules and appearance release plan]
    Present --> Consent{Single command's selected mode}
    Consent -->|Chat| Create[Create one human seat]
    Consent -->|Appearance| Pin[Pin ordered stage plan and emergency-release revision]
    Pin --> Create
    Create --> Seats[Create configured local simulated seats]
    Seats --> Warmup[Start warm-up]
    Warmup --> Deal[Deal one shared-deck hand privately]
    Deal --> Discard[Human and local strategies choose discards]
    Discard --> Resolve[Evaluate ranking and update virtual chips]
    Resolve --> Loss{Human loses after warm-up?}
    Loss -->|No| Continue{Round/session limit reached?}
    Loss -->|Yes, chat-only| Marker[Increment fictional marker]
    Loss -->|Yes, appearance| Stage[Apply next configured stage; await BC observation]
    Marker --> Continue
    Stage --> Continue
    Continue -->|No| Deal
    Continue -->|Yes| End([End session; schedule cleanup if opted in])
    Safeword[/bot safeword/] --> Stop[Stop session and invoke emergency release]

Appearance and safeword sequence

sequenceDiagram
    participant Player
    participant Commands as TableCommandSuite
    participant Game as StagedTableService
    participant DB as SessionRepository
    participant Appearance as AppearanceItemSetPort
    participant Release as EmergencyReleasePort
    participant Actions as GuardedAppearanceActions
    participant BC as BcClient / BC

    Player->>Commands: join accept appearance
    Commands->>Game: join(member, appearance)
    Game->>DB: persist consent + pinned ordered plan/release revision
    Player->>Commands: hand loss resolves
    Commands->>Game: advanceAppearance(member)
    Game->>Appearance: apply next (stripGroup, itemSet, revision)
    Appearance->>Actions: guarded, journaled mutation
    Actions->>BC: queued update
    BC-->>Game: matching observed appearance
    Game->>DB: advance stage after observation
    alt Natural end
        Game->>DB: persist cleanupDueAt
        Game->>DB: resume at deadline after restart
        Game->>Release: apply pinned release set per consented member
    else Appearance opt-out or safeword
        Player->>Commands: appearance stop / safeword
        Commands->>Game: persist stop and cancel pending progression
        Game->>Release: invoke immediately; no delay
    end
    Release->>Actions: guarded release-set mutation
    Actions->>BC: queued update
    BC-->>Game: observed completed / partial / no confirmation
    Game->>DB: persist honest cleanup state

Runtime architecture

If approved for implementation:

The feature remains unavailable until explicit gameplay approval and controlled test-room qualification. Room configs stay disabled by default.

Acceptance criteria

References