Reports are threads, and every turn of one rings the desk's bell

A player answers the desk under its reply from their lobby, proven by
the seat the report was filed from; the lobby shows the exchange in
order and says whose word is pending. A new report, a player's answer,
and a desk reply each raise a Sentry issue on the keeper's phone — the
first two from the server, the last from the reply script itself,
straight to Sentry from the droplet. The Desktop digest lists the
answers, and the desk's rule reads a report as reopened when the last
word is the player's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-21 12:08:55 -04:00
co-authored by Claude Fable 5.1
parent ffbca5bfb9
commit 11e9f950c6
7 changed files with 114 additions and 16 deletions
+9 -3
View File
@@ -220,7 +220,10 @@ export interface FeedbackReport {
round: number | null;
happened: string;
expected: string;
/** The latest word from the desk, for the lobby's one-line summary. */
reply?: { at: string; text: string; status: string };
/** The whole exchange in order: the desk's replies and the player's answers. */
thread: { at: string; text: string; from: "desk" | "player"; status?: string }[];
/** A screenshot's file name under feedback-images/, when one was sent. */
image?: string;
}
@@ -242,10 +245,12 @@ export function readFeedback(): FeedbackReport[] {
const report = reports.get(line.reportId);
if (report && typeof line.image === "string") {
report.image = line.image;
} else if (report && line.from === "player") {
report.thread.push({ at: String(line.at ?? ""), text: String(line.text ?? ""), from: "player" });
} else if (report) {
report.reply = {
at: String(line.at ?? ""), text: String(line.text ?? ""), status: String(line.status ?? "resolved"),
};
const reply = { at: String(line.at ?? ""), text: String(line.text ?? ""), status: String(line.status ?? "resolved") };
report.reply = reply;
report.thread.push({ ...reply, from: "desk" });
}
continue;
}
@@ -260,6 +265,7 @@ export function readFeedback(): FeedbackReport[] {
round: line.round == null ? null : Number(line.round),
happened: String(line.happened ?? ""),
expected: String(line.expected ?? ""),
thread: [],
});
}
return [...reports.values()];