| name | game-preview |
| description | Produce a Secret Hitler game preview as an Artifact by running the native game-report generator (never a hand-built mock). Trigger whenever the user asks to preview/show/screenshot/visualize a game, run, match, replay, transcript, report, or the UI (e.g. "show me a preview", "preview of the run", "make an artifact of my last game", "artifact of that match") — default to the fixed sample fixture, or use recent/stored/live results when asked. A "run" or "match" holds many games: list its games and pick the decisive one (or ask) rather than treating it as a single game. |
Game Preview → Artifact
When the user asks for a preview of a game (or "show me the artifact"), always
render it through the real, native generator — the self-contained
sh_export_game_report HTML (crates/engine/templates/game_report.html) — and
publish it as an Artifact. Do not hand-build a mock page; the template is the
single source of truth and shows the simultaneous discussion rounds, the
dark-red/red/blue party colors, the belief heatmap, and reliability/cost.
Pick a source
| Situation | Command | Notes |
|---|
| Default / reproducible | make game-report-json OUT=<tmp>/report.html | Renders the checked-in fixture crates/engine/fixtures/sample_game.json — a full 7-player game with discussion. No DB, deterministic. |
| Recent stored results | make game-report-stored GAME=<id> OUT=<tmp>/report.html | A real LLM game (real discussion). Requires Postgres (docker compose up -d). |
| Fresh live game | make game-report MODELS='["provider/model", ...]' OUT=<tmp>/report.html | Plays a new game. Pass LLM seats for discussion — bots don't speak, so a bot-only game has no discussion. |
Default to the fixture unless the user asks for latest/live results.
Finding a past game (when the user says "my last game" / "the run" / gives no id)
A report renders one game, but "the run" / "the match" is a batch of many.
Resolve a single game_id from the store first, then feed it to
game-report-stored:
shbench call sh_list_runs --json
shbench call sh_list_games --args '{"run_id":"<run_id>"}' --json
shbench = cargo run -q -p shbench --. Pick the most recent unless the user
names one, confirm the choice back to them, then run game-report-stored. This
needs Postgres up (docker compose up -d); if it isn't, say so and offer the
fixture instead.
Steps
- Generate the report to a scratch path (not the repo unless asked):
make game-report-json OUT=/tmp/.../report.html
- Transform the full HTML document into Artifact page-content (the Artifact
tool supplies its own
<head>/<body>):
node scripts/report_to_artifact.mjs /tmp/.../report.html /tmp/.../artifact.html
- Publish
/tmp/.../artifact.html with the Artifact tool
(favicon: 🎩, a one-line description). Redeploy to the same file path to
keep the same URL on updates.
- Show the user the Artifact URL. If they want a static image instead, screenshot
the report HTML (Playwright,
data-theme="dark", deviceScaleFactor: 2).
Refreshing the fixture
The fixture is generated by scratchpad-style builder logic; to change the sample
game, edit the record JSON at crates/engine/fixtures/sample_game.json (it must
match the GameRecord serde schema — see crates/engine/src/secret_hitler/runner/record.rs).
Guardrails
- Never fabricate a preview page — always go through
game-report*.
- The report is omniscient (reveals every party) — that's intended for the
report surface; don't add it to in-game player views.
- Keep the brand: the report already uses the party palette; see the
secret-hitler-brand skill for the wider UI brand.