The reports desk: a slip for surprises, replies in the hall

A Report button in a room's masthead files what happened and what was
expected, with a screenshot if there is one, pinned to the room and the
turn and rung through Sentry. Reports and the keeper's replies live in
feedback.jsonl beside the ledgers; the hall shows each seat's reports
with the thread under them and a line to answer. pull-reports.sh mirrors
the desk locally, report-reply.sh answers, and a skill works the desk.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
This commit is contained in:
Eric Wagoner
2026-09-23 10:12:51 -04:00
co-authored by Claude Fable 5.1
parent c49703ee4f
commit 8eca078043
11 changed files with 738 additions and 5 deletions
+9
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { page } from '$app/state';
import Board from '$lib/components/Board.svelte';
import ReportSlip from '$lib/components/ReportSlip.svelte';
import TableTalk from '$lib/components/TableTalk.svelte';
import { seatFor } from '$lib/game/client';
import { COMPACT_QUERY, Duel, NAME_MAX, playerName } from '$lib/game/duel.svelte';
@@ -13,6 +14,7 @@
let busy = $state(false);
let error = $state('');
let copied = $state(false);
let reporting = $state(false);
const link = $derived(typeof location === 'undefined' ? '' : `${location.origin}/join/${roomId}`);
const lobby = $derived(room !== null && !room.remote?.started);
@@ -118,10 +120,17 @@
{/if}
<a class="quiet" href="/guide">How to play</a>
<a class="quiet" href="/rules">Rules</a>
{#if room}
<button type="button" class="quiet" title="Something behaved unexpectedly? Tell the keeper." onclick={() => (reporting = true)}>Report</button>
{/if}
<a class="quiet" href="/">The hall</a>
</nav>
</header>
{#if room}
<ReportSlip duel={room} bind:open={reporting} />
{/if}
{#if error}
<p class="notice">{error}</p>
{/if}