[GM Workbench] Generation scratchpad/history (GenerationResult model) #138
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Motivation / Context
Today, anything generated but not saved is lost when the 2-hour Redis TTL on name-option caching expires or the tab closes (
webapp/backend/app/tasks/planning_tasks.py:11-12). There is no persistence of generated-but-unsaved options. GMs generate in bursts during prep and want to come back to results later — pick between three loot parcels, revisit a rumor they didn't use yet, re-open a backstory draft. No generation-history model exists anywhere in the schema today (confirmed: grep for loot/quest_log/generation inwebapp/backend/appreturns nothing relevant).This is issue 3 of 3 foundational items, completing the enabling layer before individual Workbench tools ship. It's also the async-status carrier for issue #136's sync/Celery split, and — per the report's hosted-service section (§6) — the natural home for future token-usage metering.
Approach
GenerationResult(§5.4), following the campaign-scoped inline-router precedent already used for planning arcs/threads (webapp/backend/app/routers/campaigns.py:3172-3390):id,campaign_id(FK CASCADE, indexed),tool_id(Text),params(JSONB),output(JSONB),status(pending/ready/failed— use raw SQL for the enum per this repo's Alembic convention, notop.create_table()withsa.Enumdirectly, to avoid spuriousCREATE TYPE),error,pinned(bool),session_id(nullable FK),created_by,created_at.token_usageJSONB column from day one (§6) — provider responses include usage data, and this is the cheapest point to start capturing it for future metering even though quota enforcement itself is out of scope here.webapp/backend/alembic/following existing conventions for JSONB + FK-cascade columns (see thePlotThread/CampaignArcmigrations for the inline-router-backed model precedent).GET /api/campaigns/{campaign_id}/workbench/history— list, filterable bytool_id,pinned.GenerationResultrows.pendingon enqueue andready/failedon completion into this table — the samegenerating → ready/failedshape the existing draft pipeline uses (draft_service.py,reminder_tasks.py:2051-2124). The frontend polls the history/status endpoint, mirroring howWikiDraftReview.jsxalready polls draft status.GenerationResultrows older than ~30 days, added alongside the existing beat schedule (find the existing periodic-cleanup task pattern inreminder_tasks.pyor the Celery beat config and follow it).params/outputback into the generation form). This can be a simple list for this issue; the full two-pane workbench layout is issue #153.Dependencies
POST /workbench/{tool_id}/generateendpoint needsGenerationResultto exist so it has somewhere to write sync results and async status. In practice these two are implemented back-to-back.Out of scope
token_usageis captured here for future metering, but enforcing quotas against it is a separate hosted-service concern (§6), not built in this issue.GeneratorPanel, right-rail redesign) — issue #153. This issue only needs a functional, minimal history list.Acceptance criteria
GenerationResultmodel + migration exist with all fields above, includingtoken_usageJSONB.GET /api/campaigns/{campaign_id}/workbench/historyreturns campaign-scoped results, filterable bytool_idandpinned, GM-only.pending → ready/failedtransitions are visible via the history endpoint (verified against at least the names tool once wired through #136, or a stub tool for this issue's own testing).Picking this up (foundation item 3/3) on
feat/138-generation-scratchpad→ PR ontofeat/v3.10-gm-workbench. Building theGenerationResultmodel + migration + campaign-scoped history/pin/delete endpoints + thepending → ready/failedlifecycle helpers (which #136's sync/async tools write into) + a retention beat task + a minimal history list. Built after #134 (merged); #136 wires the real tools into this next.Done and verified — merged into the integration branch via PR #217.
Verification (Docker): backend 674 tests (+15
test_workbench_history.py), migrationf0a1b2c3d4e5up/down/up clean; frontend 345 tests (+5) + build; ruff + eslint clean.Delivered:
GenerationResultmodel + campaign-scoped GM-only history/pin/delete endpoints + lifecycle helpers (create_result/mark_ready/mark_failed) +delete_expired+ a dailyprune_generation_resultsbeat task (pinned rows never swept) +token_usagecaptured for future metering + a minimalGenerationHistorylist (pin/delete/re-open). All three foundation items (#134/#138 + #136 next) are the enabling layer before the tools.Closing; ships to
mainwith the v3.10.0 release. Next: #136 wires the tool registry +/workbench/{tool_id}/generateendpoint into this scratchpad (names as the first registered tool).