[GM Workbench] Plot hook & rumor generator (B1) #144
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
The report ranks lore-grounded rumors (B1) among the highest-differentiation Workbench tools, second only to the session prep sheet: "not any single generator... the moat is campaign-grounded generation inside the workflow" (§6). A rumor mill that only knows generic fantasy tropes is a commodity (donjon/Perchance already do that); one that reads this campaign's lore and open plot threads and produces true/false/distorted hooks that dovetail into the plot-thread tracker is the differentiator. It's also, alongside the description generator (issue 4, #141), one of the two highest value-to-effort tools with zero overlap risk against existing issues.
Tagged TT in the report — it can ride v3.7.0 Table Tools alongside the rest of the recording→recap→wiki→table pipeline instead of waiting on the full GM Workbench milestone, since its only hard dependency is the Phase 0 foundation.
Approach
rumor/plot_hooktool in theGENERATOR_TOOLSregistry (generation_service.py, #136).game_system. Context assembled vialore_context(db, campaign_id, entry_ids=..., limit=...)andthreads_context(db, campaign_id)(both from #136's context-builder set, §5.3) — pulling in openPlotThreads and arc statuses so hooks are grounded in what's actually unresolved in the campaign, not generic filler.true/false/distorted, viagenerate_structured_textin JSON mode. Small output → runs inline (sync_allowed=True).GenerationResult(scratch, #138) by default. One-click "add as PlotThread" creates aPlotThreadrow (GM-private by default, matching howPlotThreadCRUD already works,campaigns.py:3322-3390). This is deliberately generic — it does not target the player-visible quest concept.Dependencies
statusandplayer_visiblefields toPlotThread. This tool's "add as PlotThread" always creates a GM-private thread (player_visible=falseif #115 has landed, or simply the pre-#115 shape otherwise); once #115 ships, a GM can promote a rumor-generated thread to player-visible from the existing thread UI. No coupling required in either direction — this issue does not need #115 to ship first, and does not modify #115's schema.Out of scope
PlotThread's schema (status/visibility fields) — owned entirely by #115.Acceptance criteria
rumortool registered and reachable viaPOST /api/campaigns/{campaign_id}/workbench/rumor/generate, GM-only.GenerationResulthistory.PlotThreadrow correctly linked to the campaign, GM-private by default.Moved from v3.7.0 Table Tools → v3.10.0 GM Workbench (2026-07-18).
Rationale: although tagged TT (rideable on v3.7.0), this issue's hard dependency is the Phase 0 Workbench foundation — #134 (LLM-core extraction), #136 (workbench endpoint +
GENERATOR_TOOLSregistry + context builderslore_context/threads_context), #138 (GenerationResultscratchpad) — none of which exist in the code yet, and all of which live in v3.10.0. Rather than build this as a throwaway standalone generator and re-home it into the registry later (rework), it will ride with the Workbench foundation as originally designed. Decision made while completing the rest of v3.7.0 (loot #112, quest log #115, quote board #116, attendance #114, title suggestions #23 all shipped; #130 + #110 remain and are being built now).Done — merged to
feat/v3.10-gm-workbenchvia PR #220 (batched with #147 + #149, which sharegeneration_service.py).rumortool registered on the #136 engine: a batch of hooks each tagged true/false/distorted, grounded in the campaign's open plot threads (threads_context) + any picked wiki lore, persisting aGenerationResult(#138). FrontendRumorGeneratorpanel on the GM-gated planning page; "Add as plot thread" creates arumored,player_visible=falsePlotThreadvia the existingcreateThreadendpoint (#115 shipped, so the GM can later promote it). Tolerant parser (never raises). No new API/models/migrations.Verified: backend 712 passed (incl. new
test_workbench_rumor.py— happy path, 422, GM-only 403, parser tolerance), frontend 372 passed, ruff + eslint clean.