# Group Chat And Game Module Boundary mobileClaw has two group experiences that share a chat-like UI but must not share the same runtime behavior. ## 1. Normal Group Chat Normal group chat is conversation-first. - Scheduler: `GroupTurnScheduler`. - Behavior: organic replies, mentions, light multi-agent fan-out, optional stickers, task routing, tools. - Goal: make a room feel alive without requiring strict state. - Visibility: public by default. Normal group chat may invite several roles to respond and may continue short natural threads. It should never own hidden identities, voting, role abilities, win conditions, or private game channels. ## 2. Game Group Game group is state-first. - Director: `GroupGameDirector`. - Runtime: `GroupGameRuntime`. - Behavior: phase-driven turns, seats, identities, abilities, action records, judge/system judge messages, and rule-based settlement. - Goal: run a tabletop-like experiment where every utterance or action belongs to a phase and a visibility scope. - Visibility: determined by game channel, ability visibility, actor seat, team, and judge permissions. Game groups must not use normal group-chat organic continuation. A role should speak only when one of these is true: - the judge/system judge calls its seat; - the current phase opens public speech and the game director schedules it; - the user explicitly mentions it in a channel the role can see; - the role is the configured AI judge and is advancing the process. Game groups must also keep player powers tied to the runtime seat: - Abilities belong to identities or explicit seat overrides, not to the whole room. - A seat only sees and may use abilities from its assigned identity plus seat overrides. - Phase gates still apply: an identity ability is not usable until the current phase enables it. - In system-judge event windows, only the called seat may see and submit its current event abilities. - A user in `PLAYER` mode must never see host-only advance/settle controls. ## 3. Event Separation Do not treat every game thing as a normal chat message. - Public chat: table talk, public judge notices, public results. - Private action: ability use, target, reason, raw text. Visible only to the actor/private channel and host-level views. - Team action: team meeting or faction action. Visible only to that team and host-level views. - Judge stream: hidden audit trail for judge/system settlement. - Public result: sanitized summary generated by rules after settlement. - Final verdict: produced only after `roundLimit` is exhausted, using the configured `finalJudgement.criteria`; round settlement must not declare the game winner. The UI can render these inside one chat screen, but the data meaning stays separate. ## 4. Voting And Action Visibility Ability visibility is the default display contract. - `public`: actor, target, and reason can be shown in public if the ability itself is public. - `team`: show details only to the actor team; public settlement must be sanitized. - `private`: show details only to the actor/private channel; public settlement must be sanitized. - `judge`: details are judge-only; public settlement must be sanitized. The configured AI judge is a host-level observer even if it does not have a player seat. It can see private/team/judge action records for settlement, but it must not expose those details in public chat. Voting has one extra rule: only fully public votes reveal full vote tallies. If any valid vote is private/team/judge, public settlement may reveal the result, but not the full vote map. System-judge games should be process-driven, not player-controlled. The App may wait for a user player's required vote or called identity action, but phase advancement is performed by the system judge after the required AI/user actions finish. AI players must be scheduled for vote phases when they have a currently enabled vote ability, and scheduled for event phases only when their assigned identity/seat has a currently enabled event ability. Round settlement only resolves events, votes, points, out states, and sanitized public/private results. It must not decide the game's winner. When the final planned round ends, the system enters final adjudication, calls the configured AI/default model with public chat, runtime events, scores, statuses, and `finalJudgement.criteria`, then posts a public final verdict. ## 5. Current Event Layer The first runtime split is now in code: - `GameRuntimeState.events` stores game facts alongside the current action queue. - `GameEvent` records phase changes, submitted actions, submitted votes, result publication, judge control, speaker calls, and action-resolution audit records. - `GroupGameEvents` projects those facts into `GameRuntimeMessageDraft` only when a chat presentation is needed. - `MainViewModel` should write game runtime messages from event projections instead of formatting action text directly. Events are also persisted to the Room `group_game_events` table. `hiddenStateJson` keeps a bounded event cache for compatibility and quick runtime snapshots, while the table is the long-term event stream for future replay, judge audit, and viewer-specific timelines. ## 6. Future Work The event table is now projected into viewer timelines: - `GameTimeline`: derived visible timeline per viewer. - `GroupMessage`: only the chat/presentation projection. - event replay: rebuild the runtime state from `group_game_events` for debugging or imported games. Game behavior should keep routing through `GroupGameDirector` and `GroupGameRuntime`, not through normal chat fan-out.