# SheevChat Declarative Chat Game v2

`sheevchat-chat-game-v2` is the genre-neutral Marketplace runtime for command-driven games. The desktop owns safety, persistence, identity, transactions, and output delivery. The package owns all game names, rules, resources, commands, settings, tables, prompts, messages, and optional overlay declarations.

This is the active creator contract in SheevChat 2.8 prerelease builds. New packages use `schemaVersion: 2`; schema-v1 packages are historical validation inputs and are not templates for the active runtime.

## Package envelope

A source release lives under the Marketplace `chat-games/<package-id>/<version>/` directory and contains a root `manifest.json`, root icon, and `marketplace.json`. The downloadable `.sheevpack` excludes `marketplace.json`, cannot exceed 25 MB, and cannot contain JavaScript, SQL, executables, command scripts, or unsafe paths.

The package may depend on `action_library`, `widget_pack`, `theme_pack`, `community_pack`, `chat_game`, or `builtin_widget` entries. Catalog trust values are `official_sheevchat`, `verified_partner`, `verified_creator`, `marketplace_verified`, `community`, `local_import`, and `unverified`; trust never grants additional runtime capabilities.

## Design boundary

A chat-game package is JSON data. It cannot contain or execute JavaScript, SQL, shell commands, filesystem access, arbitrary network requests, Electron APIs, or unrestricted expressions. A package may only compose operations registered by the installed runtime. Remote content can use a named host-controlled provider adapter; packages never provide request URLs. Unsupported capabilities require a newer SheevChat version.

No resource is mandatory. A game may use SheevChat loyalty, package counters, inventory-style resources, all three, or none. Loyalty is an explicit resource with `kind: "loyalty"`; it is never inferred from the game genre.

## Supported capability families

- `managed_commands` — protected package commands with normal authority, platform, and cooldown controls.
- `loyalty_resource` — optional atomic reads and adjustments of the channel's configured loyalty balance.
- `package_resources` and `inventory` — package-isolated numeric balances and collections.
- `weighted_random` — bounded package tables with cryptographically sourced selection.
- `prompt_banks` — bounded prompt/content pools with package-scoped anti-repeat history.
- `remote_prompt_sources` — cached prompt pools from a host-approved provider with bounded requests, field mapping, and safe text transforms.
- `scoped_state` — typed viewer, pair, channel, round, and stream values.
- `sessions` and `multiplayer` — bounded open/join/leave/close lifecycles and participant identity locks.
- `community_state` — channel-scoped contributions and goals.
- `voting` — one ballot entry per linked viewer with bounded tally output.
- `overlay_events` — package-declared snapshots and animation events; overlays never settle outcomes or mutate authoritative state.

## Generic operations

Commands declare at most 64 top-level operations. Nested `when` and `repeat` blocks remain subject to validation and runtime budgets.

| Operation | Purpose |
| --- | --- |
| `require` | Compare two bounded values and emit a package-authored instructional error. |
| `resource` | Atomically add or remove an optional loyalty or package resource. |
| `set`, `increment`, `contribute` | Mutate declared scoped state. |
| `choose` | Select from a declared weighted table and apply its declared effects. |
| `prompt`, `history` | Select content and maintain anti-repeat history. |
| `session_open`, `session_join`, `session_leave`, `session_close` | Manage bounded multiplayer/community sessions. |
| `vote`, `vote_tally` | Record a unique viewer vote and read the generic tally. |
| `leaderboard` | Read a bounded package-resource leaderboard. |
| `when`, `repeat` | Run bounded declarative branches or repetitions. |
| `emit_overlay` | Publish a bounded package event after the authoritative transaction succeeds. |

## Remote prompt sources

`promptSources` may supply a bank used by the normal `prompt` operation. The first registered provider is `random-word-api`. Its host and route are fixed by SheevChat; the package may declare only bounded language, count, difficulty, length, cache, and field-mapping options.

Mapped fields support `identity`, `lowercase`, `uppercase`, and `shuffle_characters` transforms. SheevChat accepts HTTPS JSON only, blocks redirects, limits request time and response size, filters malformed words, and persists a package/source cache. An expired cache remains available during a provider outage; if no cached content exists, the command reports that its remote prompt source is temporarily unavailable.

## Values and templates

Operations may use literals, `{ "ref": "..." }` references, or bounded `calc` objects. Registered calculations are `add`, `subtract`, `multiply`, `divide`, `floor`, `ceil`, `negate`, `minimum`, `maximum`, and `basis_points`.

Responses and errors use safe placeholders such as:

```text
{identity.username}
{args.quantity}
{setting.price}
{context.pointsName}
{context.commands.play}
{resource.tokens.balance}
{state.streak}
{result.reward.label}
{error.required}
{error.short}
```

Unknown placeholders become empty text. Output is capped by the host. Templates cannot call functions or evaluate code.

`context.commands.<command-id>` resolves to that installed command's effective local trigger. Use it whenever one command teaches or references another. This keeps help text correct after the streamer renames a Marketplace command or SheevChat assigns a collision-safe alternative.

## Command ownership and instructions

The host owns the shared command namespace in this order: SheevChat built-in commands and aliases, custom commands and aliases, then Marketplace commands and aliases. A Marketplace install never replaces a higher-priority command. When a primary trigger collision appears, SheevChat tries the command's declared `alternativeTriggers` in order and finally assigns a deterministic package-scoped fallback. The selected trigger is persisted so removing the higher-priority command does not unexpectedly rename the game again.

`aliases` are active at the same time as the effective primary trigger and are appropriate for common spelling, singular/plural, or familiar-name variants. `alternativeTriggers` are not aliases: they are ordered candidates for replacing the primary trigger only when its preferred name is unavailable. Package aliases that collide with a higher-priority owner are skipped. Streamers can customize or reset aliases from the installed command card without modifying the package.

Streamers may rename an installed Marketplace command. Explicit renames cannot claim a built-in, custom, or other Marketplace command. Resetting requests the package default, but the host still selects a safe alternative when that default is occupied.

Every game should provide:

- a short `management.summary`;
- concrete rules rather than generic contract language;
- a `How to play` management section listing exact syntax and what each play command does;
- one dedicated `!howto...` command that explains the full game in chat; and
- specific command descriptions that remain useful in the Commands drawer and `!cmdsearch`.

Choose a canonical trigger that says what the command does and avoids known built-in names. Declare a small `aliases` list for genuinely useful variants and an ordered `alternativeTriggers` list with equally understandable collision fallbacks. Do not generate broad or arbitrary aliases inside the package.

## Persistence and transactions

- Package state is keyed by package ID and cannot read another package's data.
- Existing `chat_game_counter_balances` rows remain the authoritative store for package numeric resources, allowing package upgrades to preserve balances when IDs remain stable.
- Command mutations run inside a SQLite transaction and use the incoming message ID as an idempotency key when available.
- Replaying the same key with the same payload returns the stored result; changing its payload is rejected.
- Failed requirements or mutations roll back the entire command.
- Viewer, session, vote, history, and output sizes are bounded by the host contract.
- Uninstall removes the installed package and unregisters its commands, but current package-owned database state is retained for a later reinstall. A package cannot execute uninstall code or request arbitrary host-data deletion.

## Optional overlays

The package may declare supported event and snapshot names in `overlay`. Placement is always explicit. The desktop remains authoritative and sends only bounded snapshots/events through the Marketplace widget bridge. An iframe cannot grant rewards, change balances, select outcomes, or bypass command permissions.

Use `overlay.companionPackageId` when a game has an optional visual companion. The companion is a separate `widget_pack` that depends on the `chat_game`, runs in the sandboxed `sheevchat-widget` lane, and subscribes to package-scoped listeners in the form `game.<game-package-id>.<event-id>`. Keeping the packages separate prevents executable widget code from entering the authoritative game lane while still allowing both packages to be presented as one compound experience.

The parent delivers a committed event to an exact subscription such as `game.sheevchat-party-wheel.wheel-spin`; a widget may instead subscribe to the generic `game` alias when it intentionally handles more than one game event. Idempotent command replays do not resend overlay animations, and browser-source reloads do not replay game events.

## Creator checklist

1. Use `schemaVersion: 2`, `type: "chat_game"`, and `runtime: "sheevchat-chat-game-v2"`.
2. Declare only the capabilities the package actually uses.
3. Keep IDs stable across versions when balances or settings must migrate.
4. Give every managed command a sensible trigger, ordered fallback triggers where useful, a specific description, bounded arguments, steps, and a response.
5. Add package-authored How to Play content and one discoverable `!howto...` command that references effective triggers through `context.commands`.
6. Use package-authored errors to explain balances, shortages, and recovery commands.
7. Declare the minimum compatible SheevChat version in `marketplace.json`.
8. Run Marketplace validation and desktop contract validation before publishing.

