feat: correct an event and regenerate the summary (#424) #602
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/424-correct-and-recompose"
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?
Part of #424, the correct-and-recompose half; the design decisions are on the issue.
The motivating case. Some errors are true to the transcript, so no model or detector can catch them. The GM said "You're in Ironroot Hold", meaning "you were". The event verified, and every summary since has put the party in Ironroot Hold. Now the GM rewrites that one event and regenerates.
What it does
gm_action∈ {struck, rewritten}, plusgm_original_summary,recomposed_from_run_idandcorrected_by_id.previous_summary, and "Restore the summary from before" puts it back.problemsstay recorded._summarise_from_beatsmoved verbatim intocompose_from_validations, and a test pins that process_audio and a recompose send the same compose request for the same beats.Async status
Follows the session lore run (
POST /sessions/{id}/lore-proposals/generate), the closest GM-triggered LLM job with a status the page can poll:sessions: status, error, requested_at, run_id.Endpoints (GM-only, documented in
docs/API.md)POST /api/sessions/{id}/summarisation-runs/{run_id}/recompose→ 202GET /api/sessions/{id}/summary-recomposePOST /api/sessions/{id}/summarisation-runs/{run_id}/restore-previous-summaryWorth reviewing
previous_summarywithout saving the text it replaces. Hand edits made after a regenerate are lost on restore, and the confirmation says so.character_name, so the member's first character is used. The prompt can only differ where a per-session character override was in effect.9e0f1a2b3c4d(down8d9e0f1a2b3c).summary_recompose_run_idis deliberately not a foreign key, to avoid asessions↔summarisation_runscycle.Checked
checkandformat --checkare clean.🤖 Generated with Claude Code
Some summary errors are true to the transcript, so no model or detector can catch them: the GM said "You're in Ironroot Hold", meaning "you were", the event verified, and every summary since put the party there. A GM can now strike an event or rewrite its text in the event log, and regenerate the summary from the corrected list. Runs stay append-only. Regenerate writes a new run: a copy of the source run's beats with the corrections applied (gm_action struck/rewritten plus gm_original_summary), recomposed_from_run_id, corrected_by_id, and previous_summary holding the summary it replaced. The source run is never touched. Only the compose step runs, using the source run's stored speaker legend: no re-extraction, no transcription. The compose step is shared, not copied: everything after validation in _summarise_from_beats moved verbatim into compose_from_validations, and the prompt header into summary_header, so process_audio and a recompose send the same compose request for the same beats (pinned on the wire). A rewritten beat is narrated even if it failed validation, keeping its problems; struck beats never reach compose. Asynchronous, GM-only (get_session_for_gm): - POST /sessions/{id}/summarisation-runs/{run_id}/recompose -> 202, a Celery task composes. 409 while a job is pending and fresh; a job pending over 30 minutes may be superseded and the old worker discards its result. A reprocess that lands meanwhile fails the job rather than being overwritten. - GET /sessions/{id}/summary-recompose: pending/done/failed, error, requested_at, run_id, stale. - POST /sessions/{id}/summarisation-runs/{run_id}/restore-previous-summary. Status follows the lore-proposals/generate precedent (status columns on the session, stale supersede, enqueue failure recorded as failed), exposed on its own GM-only endpoint rather than SessionResponse. Approval mirrors a hand edit: PATCH can change an approved summary without withdrawing approval, so regenerate and restore are not blocked either; the confirmation points to "Withdraw approval" for a Discord repost. A failure leaves sessions.summary untouched and is shown. The event log renders per viewer: players get corrected text and never a struck event; the GM sees struck events struck through and the original wording of rewritten ones. Migration 9e0f1a2b3c4d, raw DDL. sessions.summary_recompose_run_id is deliberately not a foreign key, to avoid a sessions <-> summarisation_runs cycle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>