A summary reaches Discord only once the GM approves it; the accuracy check moves into Quest Board (D96, D105, bot contract 2, lane 4) #810
Loading…
Reference in a new issue
No description provided.
Delete branch "build/lane4-discord-on-approval"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lane 4 (#730). D96, D105, and D95 (one approval, which the server already had).
⚠ Upgrade the backend and bot together:
BOT_CONTRACT_VERSION1 → 2This is the first contract bump. A version-1 bot reads a withheld summary as "nothing was recorded". Its
/recapwould tell people to record the session again, and the session-completed post would say "No recap yet — Use/record". The bot is changed to say the summary is waiting for the GM's approval.What changed
Processing posts nothing to Discord.
transcript_failednotification ("A recording could not be transcribed · Session N"), and nothing goes to the channel. It is on the grid under GM tasks, so email follows the GM's settings.Approval posts the summary. It is the first post, or, for a session whose draft went out before this change, the old delete-then-repost.
No unapproved summary text reaches Discord by any route. One rule, in
app/services/discord_summary.py(content_approved_at IS NOT NULL OR summary_discord_message_id IS NOT NULL), gates:/api/bot/sessions/{id}/summary, which feeds/recapand the session-completed excerpt, and carries an additivesummary_status;/history's list;/history's summaries;/ask's sources.The public party tally is no longer sent to the bot.
D105: summaries already posted before the upgrade count as cleared, since they are public already. Only a summary never posted waits for approval.
The accuracy check is in Quest Board.
PUTandDELETE /api/sessions/{id}/transcript-feedbacktake{rating: accurate|issues|wrong}.my_feedback; the tally is for GMs only.The bell draws
transcript_failed(NOTE_KIND).Docs:
CLAUDE.md's andbot/CLAUDE.md's pipeline descriptions (owner-approved),ARCHITECTURE.md,docs/API.md,docs/INTEGRATIONS.md, and D105 in the decisions table, with the catalogue rebuilt and all coverage scripts passing.Migration
d6e7f8a9b1c2widens the notification-kind CHECK. It is chained afterd7e8f9a0b1c3(#809), and the single-head pin moved totest_summary_on_approval.Checks, on the tree merged with main (#807–#809)
Known edges
session_notesstill show publicly in/recap, as before. The notes model PR (D97) feeds that from the table note.🤖 Generated with Claude Code
The table's accuracy check used to be reactions on the Discord draft, which no longer exists. It moves to the app: - PUT /api/sessions/{id}/transcript-feedback {rating: accurate|issues|wrong} upserts the caller's one row in transcript_feedback (a single INSERT ... ON CONFLICT, so a double click cannot 500 on the unique key); DELETE removes only the caller's row and is idempotent. Any member of the campaign (403 otherwise), only while the session has a summary, and 409 once the GM has approved it. The bot's reaction endpoints stay, for drafts already in channels, and share the same row. - Its own path, not /feedback: that is the star-and-wish prompt's (#727), where a DELETE would read as withdrawing a star, which the prompt forbids. - GET /api/sessions/{id} carries `my_feedback` (the caller's own answer) for every member. `transcript_feedback_counts` is now GM-only: a counts object for a GM, zeros before anyone answers, and null for a player, who used to receive it too. Approval's docstring and comment now say what it is: the first and only post to Discord. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>CHANGELOG [webapp] Changed bullet; API.md documents PUT/DELETE /api/sessions/{id}/transcript-feedback, `my_feedback`, the GM-only `transcript_feedback_counts`, and the `transcript_failed` kind in the bell; ARCHITECTURE.md and INTEGRATIONS.md stop describing a draft posted when processing finishes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>The draft post at processing was the loud route. These were the quiet ones, now all on the GM's sign-off, `content_approved_at`: - The final reminder's "Previously on" excerpt selected on the audio being trashed/approved, a stand-in for approval that "bin it once transcribed" broke by trashing audio at processing. It selects on content_approved_at. - GET /api/bot/sessions/{id}/summary (/recap, and the session-completed embed's excerpt) returns `summary: null` until approval, with an additive `summary_status: "approved" | "awaiting_approval" | null`, and never the accuracy tally (`feedback_counts: null`), which /recap posted publicly. - GET /api/bot/guilds/{g}/sessions/list marks has_summary (/history's ✦, which points at /recap) for approved summaries only. - GET /api/bot/guilds/{g}/sessions/history returns approved summaries only. - POST /api/bot/guilds/{g}/sessions/ask answers from approved summaries only, and says `reason: "awaiting_approval"` when summaries exist and none is approved yet. Why the bump: a version-1 bot reads the withheld null as "nothing was recorded". /recap (cogs/sessions.py, `if not has_summary and not has_notes`) told the reader "No transcript or GM notes have been recorded ... Use /record start", and the session-completed embed (cogs/notifications.py, `else:` branch) nudged the GM to record — both false for a recorded session awaiting approval, and both an invitation to record it twice. The bot now says the summary is waiting for the GM's approval in both places, and in /ask for the new reason. BOT_CONTRACT_VERSION goes to 2 on both sides, with the pinning tests; check_version_sync passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>The owner's decision: a summary the bot posted as a draft before D96 is public already, so gating it protects nothing. Only a summary that has never been posted waits for approval. One rule in one place, app/services/discord_summary.py: summary_cleared_for_discord(session) and its SQL form, content_approved_at IS NOT NULL OR summary_discord_message_id IS NOT NULL. Every gated route now uses it: the final reminder's "Previously on", GET /api/bot/sessions/{id}/summary (/recap and the session-completed excerpt), /list's has_summary, /history, and /ask, including /ask's "awaiting approval" count, which now counts only summaries not cleared. summary_status stays "approved" for a cleared summary; the bot only ever tests for "awaiting_approval", so it needs no third value and no bot change. summary_discord_message_id is never cleared: only the bot's summary-message-id endpoint writes it, approval sends it to the bot to delete that draft and leaves the column as it is, and since D96 nothing asks for a new draft. Tests: every route has a case with no approval and a stored message id (shown) beside one with neither (waits), plus the rule's truth table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>